]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
define GLSL version explicitly to work around a problem with ATI/AMD drivers not...
[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_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
146 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
147 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
148 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
149 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
150 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)"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158
159 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)"};
160 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
161 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"};
162 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
163 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
164 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
165
166 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
167 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
168 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
169 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
170
171 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
172 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
173 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
174 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
175 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
176 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
177 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
178
179 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
180 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
181 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
182 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)"};
183 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
184 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
185 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
186 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
188 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
189
190 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"};
191
192 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"};
193
194 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
195
196 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
197 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"};
198 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
199 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
200 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
201 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
202 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)"};
203 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
204 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
205
206 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
207 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"};
208
209 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)"};
210
211 extern cvar_t v_glslgamma;
212
213 extern qboolean v_flipped_state;
214
215 static struct r_bloomstate_s
216 {
217         qboolean enabled;
218         qboolean hdr;
219
220         int bloomwidth, bloomheight;
221
222         int screentexturewidth, screentextureheight;
223         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
224
225         int bloomtexturewidth, bloomtextureheight;
226         rtexture_t *texture_bloom;
227
228         // arrays for rendering the screen passes
229         float screentexcoord2f[8];
230         float bloomtexcoord2f[8];
231         float offsettexcoord2f[8];
232
233         r_viewport_t viewport;
234 }
235 r_bloomstate;
236
237 r_waterstate_t r_waterstate;
238
239 /// shadow volume bsp struct with automatically growing nodes buffer
240 svbsp_t r_svbsp;
241
242 rtexture_t *r_texture_blanknormalmap;
243 rtexture_t *r_texture_white;
244 rtexture_t *r_texture_grey128;
245 rtexture_t *r_texture_black;
246 rtexture_t *r_texture_notexture;
247 rtexture_t *r_texture_whitecube;
248 rtexture_t *r_texture_normalizationcube;
249 rtexture_t *r_texture_fogattenuation;
250 rtexture_t *r_texture_fogheighttexture;
251 rtexture_t *r_texture_gammaramps;
252 unsigned int r_texture_gammaramps_serial;
253 //rtexture_t *r_texture_fogintensity;
254 rtexture_t *r_texture_reflectcube;
255
256 // TODO: hash lookups?
257 typedef struct cubemapinfo_s
258 {
259         char basename[64];
260         rtexture_t *texture;
261 }
262 cubemapinfo_t;
263
264 int r_texture_numcubemaps;
265 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
266
267 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
268 unsigned int r_numqueries;
269 unsigned int r_maxqueries;
270
271 typedef struct r_qwskincache_s
272 {
273         char name[MAX_QPATH];
274         skinframe_t *skinframe;
275 }
276 r_qwskincache_t;
277
278 static r_qwskincache_t *r_qwskincache;
279 static int r_qwskincache_size;
280
281 /// vertex coordinates for a quad that covers the screen exactly
282 extern const float r_screenvertex3f[12];
283 extern const float r_d3dscreenvertex3f[12];
284 const float r_screenvertex3f[12] =
285 {
286         0, 0, 0,
287         1, 0, 0,
288         1, 1, 0,
289         0, 1, 0
290 };
291 const float r_d3dscreenvertex3f[12] =
292 {
293         0, 1, 0,
294         1, 1, 0,
295         1, 0, 0,
296         0, 0, 0
297 };
298
299 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
300 {
301         int i;
302         for (i = 0;i < verts;i++)
303         {
304                 out[0] = in[0] * r;
305                 out[1] = in[1] * g;
306                 out[2] = in[2] * b;
307                 out[3] = in[3];
308                 in += 4;
309                 out += 4;
310         }
311 }
312
313 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
314 {
315         int i;
316         for (i = 0;i < verts;i++)
317         {
318                 out[0] = r;
319                 out[1] = g;
320                 out[2] = b;
321                 out[3] = a;
322                 out += 4;
323         }
324 }
325
326 // FIXME: move this to client?
327 void FOG_clear(void)
328 {
329         if (gamemode == GAME_NEHAHRA)
330         {
331                 Cvar_Set("gl_fogenable", "0");
332                 Cvar_Set("gl_fogdensity", "0.2");
333                 Cvar_Set("gl_fogred", "0.3");
334                 Cvar_Set("gl_foggreen", "0.3");
335                 Cvar_Set("gl_fogblue", "0.3");
336         }
337         r_refdef.fog_density = 0;
338         r_refdef.fog_red = 0;
339         r_refdef.fog_green = 0;
340         r_refdef.fog_blue = 0;
341         r_refdef.fog_alpha = 1;
342         r_refdef.fog_start = 0;
343         r_refdef.fog_end = 16384;
344         r_refdef.fog_height = 1<<30;
345         r_refdef.fog_fadedepth = 128;
346         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
347 }
348
349 static void R_BuildBlankTextures(void)
350 {
351         unsigned char data[4];
352         data[2] = 128; // normal X
353         data[1] = 128; // normal Y
354         data[0] = 255; // normal Z
355         data[3] = 128; // height
356         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
357         data[0] = 255;
358         data[1] = 255;
359         data[2] = 255;
360         data[3] = 255;
361         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
362         data[0] = 128;
363         data[1] = 128;
364         data[2] = 128;
365         data[3] = 255;
366         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
367         data[0] = 0;
368         data[1] = 0;
369         data[2] = 0;
370         data[3] = 255;
371         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 }
373
374 static void R_BuildNoTexture(void)
375 {
376         int x, y;
377         unsigned char pix[16][16][4];
378         // this makes a light grey/dark grey checkerboard texture
379         for (y = 0;y < 16;y++)
380         {
381                 for (x = 0;x < 16;x++)
382                 {
383                         if ((y < 8) ^ (x < 8))
384                         {
385                                 pix[y][x][0] = 128;
386                                 pix[y][x][1] = 128;
387                                 pix[y][x][2] = 128;
388                                 pix[y][x][3] = 255;
389                         }
390                         else
391                         {
392                                 pix[y][x][0] = 64;
393                                 pix[y][x][1] = 64;
394                                 pix[y][x][2] = 64;
395                                 pix[y][x][3] = 255;
396                         }
397                 }
398         }
399         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
400 }
401
402 static void R_BuildWhiteCube(void)
403 {
404         unsigned char data[6*1*1*4];
405         memset(data, 255, sizeof(data));
406         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
407 }
408
409 static void R_BuildNormalizationCube(void)
410 {
411         int x, y, side;
412         vec3_t v;
413         vec_t s, t, intensity;
414 #define NORMSIZE 64
415         unsigned char *data;
416         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
417         for (side = 0;side < 6;side++)
418         {
419                 for (y = 0;y < NORMSIZE;y++)
420                 {
421                         for (x = 0;x < NORMSIZE;x++)
422                         {
423                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
425                                 switch(side)
426                                 {
427                                 default:
428                                 case 0:
429                                         v[0] = 1;
430                                         v[1] = -t;
431                                         v[2] = -s;
432                                         break;
433                                 case 1:
434                                         v[0] = -1;
435                                         v[1] = -t;
436                                         v[2] = s;
437                                         break;
438                                 case 2:
439                                         v[0] = s;
440                                         v[1] = 1;
441                                         v[2] = t;
442                                         break;
443                                 case 3:
444                                         v[0] = s;
445                                         v[1] = -1;
446                                         v[2] = -t;
447                                         break;
448                                 case 4:
449                                         v[0] = s;
450                                         v[1] = -t;
451                                         v[2] = 1;
452                                         break;
453                                 case 5:
454                                         v[0] = -s;
455                                         v[1] = -t;
456                                         v[2] = -1;
457                                         break;
458                                 }
459                                 intensity = 127.0f / sqrt(DotProduct(v, v));
460                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
461                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
462                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
463                                 data[((side*64+y)*64+x)*4+3] = 255;
464                         }
465                 }
466         }
467         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
468         Mem_Free(data);
469 }
470
471 static void R_BuildFogTexture(void)
472 {
473         int x, b;
474 #define FOGWIDTH 256
475         unsigned char data1[FOGWIDTH][4];
476         //unsigned char data2[FOGWIDTH][4];
477         double d, r, alpha;
478
479         r_refdef.fogmasktable_start = r_refdef.fog_start;
480         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
481         r_refdef.fogmasktable_range = r_refdef.fogrange;
482         r_refdef.fogmasktable_density = r_refdef.fog_density;
483
484         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
485         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
486         {
487                 d = (x * r - r_refdef.fogmasktable_start);
488                 if(developer_extra.integer)
489                         Con_DPrintf("%f ", d);
490                 d = max(0, d);
491                 if (r_fog_exp2.integer)
492                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
493                 else
494                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
495                 if(developer_extra.integer)
496                         Con_DPrintf(" : %f ", alpha);
497                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
498                 if(developer_extra.integer)
499                         Con_DPrintf(" = %f\n", alpha);
500                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
501         }
502
503         for (x = 0;x < FOGWIDTH;x++)
504         {
505                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
506                 data1[x][0] = b;
507                 data1[x][1] = b;
508                 data1[x][2] = b;
509                 data1[x][3] = 255;
510                 //data2[x][0] = 255 - b;
511                 //data2[x][1] = 255 - b;
512                 //data2[x][2] = 255 - b;
513                 //data2[x][3] = 255;
514         }
515         if (r_texture_fogattenuation)
516         {
517                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
519         }
520         else
521         {
522                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
523                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
524         }
525 }
526
527 static void R_BuildFogHeightTexture(void)
528 {
529         unsigned char *inpixels;
530         int size;
531         int x;
532         int y;
533         int j;
534         float c[4];
535         float f;
536         inpixels = NULL;
537         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
538         if (r_refdef.fogheighttexturename[0])
539                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
540         if (!inpixels)
541         {
542                 r_refdef.fog_height_tablesize = 0;
543                 if (r_texture_fogheighttexture)
544                         R_FreeTexture(r_texture_fogheighttexture);
545                 r_texture_fogheighttexture = NULL;
546                 if (r_refdef.fog_height_table2d)
547                         Mem_Free(r_refdef.fog_height_table2d);
548                 r_refdef.fog_height_table2d = NULL;
549                 if (r_refdef.fog_height_table1d)
550                         Mem_Free(r_refdef.fog_height_table1d);
551                 r_refdef.fog_height_table1d = NULL;
552                 return;
553         }
554         size = image_width;
555         r_refdef.fog_height_tablesize = size;
556         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
557         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
558         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
559         Mem_Free(inpixels);
560         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
561         // average fog color table accounting for every fog layer between a point
562         // and the camera.  (Note: attenuation is handled separately!)
563         for (y = 0;y < size;y++)
564         {
565                 for (x = 0;x < size;x++)
566                 {
567                         Vector4Clear(c);
568                         f = 0;
569                         if (x < y)
570                         {
571                                 for (j = x;j <= y;j++)
572                                 {
573                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
574                                         f++;
575                                 }
576                         }
577                         else
578                         {
579                                 for (j = x;j >= y;j--)
580                                 {
581                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
582                                         f++;
583                                 }
584                         }
585                         f = 1.0f / f;
586                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
590                 }
591         }
592         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
593 }
594
595 //=======================================================================================================================================================
596
597 static const char *builtinshaderstring =
598 #include "shader_glsl.h"
599 ;
600
601 const char *builtinhlslshaderstring =
602 #include "shader_hlsl.h"
603 ;
604
605 char *glslshaderstring = NULL;
606 char *hlslshaderstring = NULL;
607
608 //=======================================================================================================================================================
609
610 typedef struct shaderpermutationinfo_s
611 {
612         const char *pretext;
613         const char *name;
614 }
615 shaderpermutationinfo_t;
616
617 typedef struct shadermodeinfo_s
618 {
619         const char *vertexfilename;
620         const char *geometryfilename;
621         const char *fragmentfilename;
622         const char *pretext;
623         const char *name;
624 }
625 shadermodeinfo_t;
626
627 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
628 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
629 {
630         {"#define USEDIFFUSE\n", " diffuse"},
631         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
632         {"#define USEVIEWTINT\n", " viewtint"},
633         {"#define USECOLORMAPPING\n", " colormapping"},
634         {"#define USESATURATION\n", " saturation"},
635         {"#define USEFOGINSIDE\n", " foginside"},
636         {"#define USEFOGOUTSIDE\n", " fogoutside"},
637         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
638         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
639         {"#define USEGAMMARAMPS\n", " gammaramps"},
640         {"#define USECUBEFILTER\n", " cubefilter"},
641         {"#define USEGLOW\n", " glow"},
642         {"#define USEBLOOM\n", " bloom"},
643         {"#define USESPECULAR\n", " specular"},
644         {"#define USEPOSTPROCESSING\n", " postprocessing"},
645         {"#define USEREFLECTION\n", " reflection"},
646         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
647         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
648         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
649         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
650         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
651         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
652         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
653         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
654         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
655         {"#define USEALPHAKILL\n", " alphakill"},
656         {"#define USEREFLECTCUBE\n", " reflectcube"},
657         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
658         {"#define USEBOUNCEGRID\n", " bouncegrid"},
659         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
660 };
661
662 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
663 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
664 {
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
667         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
681 };
682
683 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
684 {
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
701 };
702
703 struct r_glsl_permutation_s;
704 typedef struct r_glsl_permutation_s
705 {
706         /// hash lookup data
707         struct r_glsl_permutation_s *hashnext;
708         unsigned int mode;
709         unsigned int permutation;
710
711         /// indicates if we have tried compiling this permutation already
712         qboolean compiled;
713         /// 0 if compilation failed
714         int program;
715         // texture units assigned to each detected uniform
716         int tex_Texture_First;
717         int tex_Texture_Second;
718         int tex_Texture_GammaRamps;
719         int tex_Texture_Normal;
720         int tex_Texture_Color;
721         int tex_Texture_Gloss;
722         int tex_Texture_Glow;
723         int tex_Texture_SecondaryNormal;
724         int tex_Texture_SecondaryColor;
725         int tex_Texture_SecondaryGloss;
726         int tex_Texture_SecondaryGlow;
727         int tex_Texture_Pants;
728         int tex_Texture_Shirt;
729         int tex_Texture_FogHeightTexture;
730         int tex_Texture_FogMask;
731         int tex_Texture_Lightmap;
732         int tex_Texture_Deluxemap;
733         int tex_Texture_Attenuation;
734         int tex_Texture_Cube;
735         int tex_Texture_Refraction;
736         int tex_Texture_Reflection;
737         int tex_Texture_ShadowMap2D;
738         int tex_Texture_CubeProjection;
739         int tex_Texture_ScreenDepth;
740         int tex_Texture_ScreenNormalMap;
741         int tex_Texture_ScreenDiffuse;
742         int tex_Texture_ScreenSpecular;
743         int tex_Texture_ReflectMask;
744         int tex_Texture_ReflectCube;
745         int tex_Texture_BounceGrid;
746         /// locations of detected uniforms in program object, or -1 if not found
747         int loc_Texture_First;
748         int loc_Texture_Second;
749         int loc_Texture_GammaRamps;
750         int loc_Texture_Normal;
751         int loc_Texture_Color;
752         int loc_Texture_Gloss;
753         int loc_Texture_Glow;
754         int loc_Texture_SecondaryNormal;
755         int loc_Texture_SecondaryColor;
756         int loc_Texture_SecondaryGloss;
757         int loc_Texture_SecondaryGlow;
758         int loc_Texture_Pants;
759         int loc_Texture_Shirt;
760         int loc_Texture_FogHeightTexture;
761         int loc_Texture_FogMask;
762         int loc_Texture_Lightmap;
763         int loc_Texture_Deluxemap;
764         int loc_Texture_Attenuation;
765         int loc_Texture_Cube;
766         int loc_Texture_Refraction;
767         int loc_Texture_Reflection;
768         int loc_Texture_ShadowMap2D;
769         int loc_Texture_CubeProjection;
770         int loc_Texture_ScreenDepth;
771         int loc_Texture_ScreenNormalMap;
772         int loc_Texture_ScreenDiffuse;
773         int loc_Texture_ScreenSpecular;
774         int loc_Texture_ReflectMask;
775         int loc_Texture_ReflectCube;
776         int loc_Texture_BounceGrid;
777         int loc_Alpha;
778         int loc_BloomBlur_Parameters;
779         int loc_ClientTime;
780         int loc_Color_Ambient;
781         int loc_Color_Diffuse;
782         int loc_Color_Specular;
783         int loc_Color_Glow;
784         int loc_Color_Pants;
785         int loc_Color_Shirt;
786         int loc_DeferredColor_Ambient;
787         int loc_DeferredColor_Diffuse;
788         int loc_DeferredColor_Specular;
789         int loc_DeferredMod_Diffuse;
790         int loc_DeferredMod_Specular;
791         int loc_DistortScaleRefractReflect;
792         int loc_EyePosition;
793         int loc_FogColor;
794         int loc_FogHeightFade;
795         int loc_FogPlane;
796         int loc_FogPlaneViewDist;
797         int loc_FogRangeRecip;
798         int loc_LightColor;
799         int loc_LightDir;
800         int loc_LightPosition;
801         int loc_OffsetMapping_ScaleSteps;
802         int loc_PixelSize;
803         int loc_ReflectColor;
804         int loc_ReflectFactor;
805         int loc_ReflectOffset;
806         int loc_RefractColor;
807         int loc_Saturation;
808         int loc_ScreenCenterRefractReflect;
809         int loc_ScreenScaleRefractReflect;
810         int loc_ScreenToDepth;
811         int loc_ShadowMap_Parameters;
812         int loc_ShadowMap_TextureScale;
813         int loc_SpecularPower;
814         int loc_UserVec1;
815         int loc_UserVec2;
816         int loc_UserVec3;
817         int loc_UserVec4;
818         int loc_ViewTintColor;
819         int loc_ViewToLight;
820         int loc_ModelToLight;
821         int loc_TexMatrix;
822         int loc_BackgroundTexMatrix;
823         int loc_ModelViewProjectionMatrix;
824         int loc_ModelViewMatrix;
825         int loc_PixelToScreenTexCoord;
826         int loc_ModelToReflectCube;
827         int loc_ShadowMapMatrix;
828         int loc_BloomColorSubtract;
829         int loc_NormalmapScrollBlend;
830         int loc_BounceGridMatrix;
831         int loc_BounceGridIntensity;
832 }
833 r_glsl_permutation_t;
834
835 #define SHADERPERMUTATION_HASHSIZE 256
836
837
838 // non-degradable "lightweight" shader parameters to keep the permutations simpler
839 // these can NOT degrade! only use for simple stuff
840 enum
841 {
842         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
843         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
844         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
845         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
846         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
847         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
848 };
849 #define SHADERSTATICPARMS_COUNT 6
850
851 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
852 static int shaderstaticparms_count = 0;
853
854 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
855 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
856 qboolean R_CompileShader_CheckStaticParms(void)
857 {
858         static int r_compileshader_staticparms_save[1];
859         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
860         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
861
862         // detect all
863         if (r_glsl_saturation_redcompensate.integer)
864                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
865         if (r_shadow_glossexact.integer)
866                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
867         if (r_glsl_postprocess.integer)
868         {
869                 if (r_glsl_postprocess_uservec1_enable.integer)
870                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
871                 if (r_glsl_postprocess_uservec2_enable.integer)
872                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
873                 if (r_glsl_postprocess_uservec3_enable.integer)
874                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
875                 if (r_glsl_postprocess_uservec4_enable.integer)
876                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
877         }
878         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
879 }
880
881 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
882         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
883                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
884         else \
885                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
886 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
887 {
888         shaderstaticparms_count = 0;
889
890         // emit all
891         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
893         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
894         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
895         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
896         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
897 }
898
899 /// information about each possible shader permutation
900 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
901 /// currently selected permutation
902 r_glsl_permutation_t *r_glsl_permutation;
903 /// storage for permutations linked in the hash table
904 memexpandablearray_t r_glsl_permutationarray;
905
906 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
907 {
908         //unsigned int hashdepth = 0;
909         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
910         r_glsl_permutation_t *p;
911         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
912         {
913                 if (p->mode == mode && p->permutation == permutation)
914                 {
915                         //if (hashdepth > 10)
916                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
917                         return p;
918                 }
919                 //hashdepth++;
920         }
921         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
922         p->mode = mode;
923         p->permutation = permutation;
924         p->hashnext = r_glsl_permutationhash[mode][hashindex];
925         r_glsl_permutationhash[mode][hashindex] = p;
926         //if (hashdepth > 10)
927         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928         return p;
929 }
930
931 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
932 {
933         char *shaderstring;
934         if (!filename || !filename[0])
935                 return NULL;
936         if (!strcmp(filename, "glsl/default.glsl"))
937         {
938                 if (!glslshaderstring)
939                 {
940                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
941                         if (glslshaderstring)
942                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
943                         else
944                                 glslshaderstring = (char *)builtinshaderstring;
945                 }
946                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
947                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
948                 return shaderstring;
949         }
950         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
951         if (shaderstring)
952         {
953                 if (printfromdisknotice)
954                         Con_DPrintf("from disk %s... ", filename);
955                 return shaderstring;
956         }
957         return shaderstring;
958 }
959
960 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
961 {
962         int i;
963         int sampler;
964         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
965         char *vertexstring, *geometrystring, *fragmentstring;
966         char permutationname[256];
967         int vertstrings_count = 0;
968         int geomstrings_count = 0;
969         int fragstrings_count = 0;
970         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
971         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
972         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
973
974         if (p->compiled)
975                 return;
976         p->compiled = true;
977         p->program = 0;
978
979         permutationname[0] = 0;
980         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
981         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
982         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
983
984         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
985
986         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
987         if(vid.support.gl20shaders130)
988         {
989                 vertstrings_list[vertstrings_count++] = "#version 130\n";
990                 geomstrings_list[geomstrings_count++] = "#version 130\n";
991                 fragstrings_list[fragstrings_count++] = "#version 130\n";
992                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
993                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
994                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
995         }
996
997         // the first pretext is which type of shader to compile as
998         // (later these will all be bound together as a program object)
999         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1000         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1001         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1002
1003         // the second pretext is the mode (for example a light source)
1004         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1005         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1006         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1007         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1008
1009         // now add all the permutation pretexts
1010         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1011         {
1012                 if (permutation & (1<<i))
1013                 {
1014                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1015                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1016                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1017                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1018                 }
1019                 else
1020                 {
1021                         // keep line numbers correct
1022                         vertstrings_list[vertstrings_count++] = "\n";
1023                         geomstrings_list[geomstrings_count++] = "\n";
1024                         fragstrings_list[fragstrings_count++] = "\n";
1025                 }
1026         }
1027
1028         // add static parms
1029         R_CompileShader_AddStaticParms(mode, permutation);
1030         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1031         vertstrings_count += shaderstaticparms_count;
1032         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1033         geomstrings_count += shaderstaticparms_count;
1034         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1035         fragstrings_count += shaderstaticparms_count;
1036
1037         // now append the shader text itself
1038         vertstrings_list[vertstrings_count++] = vertexstring;
1039         geomstrings_list[geomstrings_count++] = geometrystring;
1040         fragstrings_list[fragstrings_count++] = fragmentstring;
1041
1042         // if any sources were NULL, clear the respective list
1043         if (!vertexstring)
1044                 vertstrings_count = 0;
1045         if (!geometrystring)
1046                 geomstrings_count = 0;
1047         if (!fragmentstring)
1048                 fragstrings_count = 0;
1049
1050         // compile the shader program
1051         if (vertstrings_count + geomstrings_count + fragstrings_count)
1052                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1053         if (p->program)
1054         {
1055                 CHECKGLERROR
1056                 qglUseProgram(p->program);CHECKGLERROR
1057                 // look up all the uniform variable names we care about, so we don't
1058                 // have to look them up every time we set them
1059
1060                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1061                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1062                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1063                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1064                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1065                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1066                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1067                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1068                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1069                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1070                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1071                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1072                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1073                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1074                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1075                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1076                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1077                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1078                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1079                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1080                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1081                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1082                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1083                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1084                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1085                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1086                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1087                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1088                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1089                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1090                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1091                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1092                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1093                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1094                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1095                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1096                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1097                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1098                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1099                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1100                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1101                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1102                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1103                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1104                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1105                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1106                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1107                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1108                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1109                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1110                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1111                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1112                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1113                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1114                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1115                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1116                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1117                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1118                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1119                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1120                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1121                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1122                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1123                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1124                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1125                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1126                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1127                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1128                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1129                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1130                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1131                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1132                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1133                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1134                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1135                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1136                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1137                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1138                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1139                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1140                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1141                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1142                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1143                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1144                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1145                 // initialize the samplers to refer to the texture units we use
1146                 p->tex_Texture_First = -1;
1147                 p->tex_Texture_Second = -1;
1148                 p->tex_Texture_GammaRamps = -1;
1149                 p->tex_Texture_Normal = -1;
1150                 p->tex_Texture_Color = -1;
1151                 p->tex_Texture_Gloss = -1;
1152                 p->tex_Texture_Glow = -1;
1153                 p->tex_Texture_SecondaryNormal = -1;
1154                 p->tex_Texture_SecondaryColor = -1;
1155                 p->tex_Texture_SecondaryGloss = -1;
1156                 p->tex_Texture_SecondaryGlow = -1;
1157                 p->tex_Texture_Pants = -1;
1158                 p->tex_Texture_Shirt = -1;
1159                 p->tex_Texture_FogHeightTexture = -1;
1160                 p->tex_Texture_FogMask = -1;
1161                 p->tex_Texture_Lightmap = -1;
1162                 p->tex_Texture_Deluxemap = -1;
1163                 p->tex_Texture_Attenuation = -1;
1164                 p->tex_Texture_Cube = -1;
1165                 p->tex_Texture_Refraction = -1;
1166                 p->tex_Texture_Reflection = -1;
1167                 p->tex_Texture_ShadowMap2D = -1;
1168                 p->tex_Texture_CubeProjection = -1;
1169                 p->tex_Texture_ScreenDepth = -1;
1170                 p->tex_Texture_ScreenNormalMap = -1;
1171                 p->tex_Texture_ScreenDiffuse = -1;
1172                 p->tex_Texture_ScreenSpecular = -1;
1173                 p->tex_Texture_ReflectMask = -1;
1174                 p->tex_Texture_ReflectCube = -1;
1175                 p->tex_Texture_BounceGrid = -1;
1176                 sampler = 0;
1177                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1178                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1179                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1180                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1181                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1182                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1183                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1184                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1185                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1186                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1187                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1188                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1189                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1190                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1191                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1192                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1193                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1194                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1195                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1196                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1197                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1198                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1199                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1200                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1201                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1202                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1203                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1204                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1205                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1206                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1207                 CHECKGLERROR
1208                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1209         }
1210         else
1211                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1212
1213         // free the strings
1214         if (vertexstring)
1215                 Mem_Free(vertexstring);
1216         if (geometrystring)
1217                 Mem_Free(geometrystring);
1218         if (fragmentstring)
1219                 Mem_Free(fragmentstring);
1220 }
1221
1222 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1223 {
1224         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1225         if (r_glsl_permutation != perm)
1226         {
1227                 r_glsl_permutation = perm;
1228                 if (!r_glsl_permutation->program)
1229                 {
1230                         if (!r_glsl_permutation->compiled)
1231                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1232                         if (!r_glsl_permutation->program)
1233                         {
1234                                 // remove features until we find a valid permutation
1235                                 int i;
1236                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1237                                 {
1238                                         // reduce i more quickly whenever it would not remove any bits
1239                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1240                                         if (!(permutation & j))
1241                                                 continue;
1242                                         permutation -= j;
1243                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1244                                         if (!r_glsl_permutation->compiled)
1245                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1246                                         if (r_glsl_permutation->program)
1247                                                 break;
1248                                 }
1249                                 if (i >= SHADERPERMUTATION_COUNT)
1250                                 {
1251                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1252                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1253                                         qglUseProgram(0);CHECKGLERROR
1254                                         return; // no bit left to clear, entire mode is broken
1255                                 }
1256                         }
1257                 }
1258                 CHECKGLERROR
1259                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1260         }
1261         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1262         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1263         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1264 }
1265
1266 #ifdef SUPPORTD3D
1267
1268 #ifdef SUPPORTD3D
1269 #include <d3d9.h>
1270 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1271 extern D3DCAPS9 vid_d3d9caps;
1272 #endif
1273
1274 struct r_hlsl_permutation_s;
1275 typedef struct r_hlsl_permutation_s
1276 {
1277         /// hash lookup data
1278         struct r_hlsl_permutation_s *hashnext;
1279         unsigned int mode;
1280         unsigned int permutation;
1281
1282         /// indicates if we have tried compiling this permutation already
1283         qboolean compiled;
1284         /// NULL if compilation failed
1285         IDirect3DVertexShader9 *vertexshader;
1286         IDirect3DPixelShader9 *pixelshader;
1287 }
1288 r_hlsl_permutation_t;
1289
1290 typedef enum D3DVSREGISTER_e
1291 {
1292         D3DVSREGISTER_TexMatrix = 0, // float4x4
1293         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1294         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1295         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1296         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1297         D3DVSREGISTER_ModelToLight = 20, // float4x4
1298         D3DVSREGISTER_EyePosition = 24,
1299         D3DVSREGISTER_FogPlane = 25,
1300         D3DVSREGISTER_LightDir = 26,
1301         D3DVSREGISTER_LightPosition = 27,
1302 }
1303 D3DVSREGISTER_t;
1304
1305 typedef enum D3DPSREGISTER_e
1306 {
1307         D3DPSREGISTER_Alpha = 0,
1308         D3DPSREGISTER_BloomBlur_Parameters = 1,
1309         D3DPSREGISTER_ClientTime = 2,
1310         D3DPSREGISTER_Color_Ambient = 3,
1311         D3DPSREGISTER_Color_Diffuse = 4,
1312         D3DPSREGISTER_Color_Specular = 5,
1313         D3DPSREGISTER_Color_Glow = 6,
1314         D3DPSREGISTER_Color_Pants = 7,
1315         D3DPSREGISTER_Color_Shirt = 8,
1316         D3DPSREGISTER_DeferredColor_Ambient = 9,
1317         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1318         D3DPSREGISTER_DeferredColor_Specular = 11,
1319         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1320         D3DPSREGISTER_DeferredMod_Specular = 13,
1321         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1322         D3DPSREGISTER_EyePosition = 15, // unused
1323         D3DPSREGISTER_FogColor = 16,
1324         D3DPSREGISTER_FogHeightFade = 17,
1325         D3DPSREGISTER_FogPlane = 18,
1326         D3DPSREGISTER_FogPlaneViewDist = 19,
1327         D3DPSREGISTER_FogRangeRecip = 20,
1328         D3DPSREGISTER_LightColor = 21,
1329         D3DPSREGISTER_LightDir = 22, // unused
1330         D3DPSREGISTER_LightPosition = 23,
1331         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1332         D3DPSREGISTER_PixelSize = 25,
1333         D3DPSREGISTER_ReflectColor = 26,
1334         D3DPSREGISTER_ReflectFactor = 27,
1335         D3DPSREGISTER_ReflectOffset = 28,
1336         D3DPSREGISTER_RefractColor = 29,
1337         D3DPSREGISTER_Saturation = 30,
1338         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1339         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1340         D3DPSREGISTER_ScreenToDepth = 33,
1341         D3DPSREGISTER_ShadowMap_Parameters = 34,
1342         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1343         D3DPSREGISTER_SpecularPower = 36,
1344         D3DPSREGISTER_UserVec1 = 37,
1345         D3DPSREGISTER_UserVec2 = 38,
1346         D3DPSREGISTER_UserVec3 = 39,
1347         D3DPSREGISTER_UserVec4 = 40,
1348         D3DPSREGISTER_ViewTintColor = 41,
1349         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1350         D3DPSREGISTER_BloomColorSubtract = 43,
1351         D3DPSREGISTER_ViewToLight = 44, // float4x4
1352         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1353         D3DPSREGISTER_NormalmapScrollBlend = 52,
1354         // next at 53
1355 }
1356 D3DPSREGISTER_t;
1357
1358 /// information about each possible shader permutation
1359 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1360 /// currently selected permutation
1361 r_hlsl_permutation_t *r_hlsl_permutation;
1362 /// storage for permutations linked in the hash table
1363 memexpandablearray_t r_hlsl_permutationarray;
1364
1365 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1366 {
1367         //unsigned int hashdepth = 0;
1368         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1369         r_hlsl_permutation_t *p;
1370         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1371         {
1372                 if (p->mode == mode && p->permutation == permutation)
1373                 {
1374                         //if (hashdepth > 10)
1375                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1376                         return p;
1377                 }
1378                 //hashdepth++;
1379         }
1380         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1381         p->mode = mode;
1382         p->permutation = permutation;
1383         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1384         r_hlsl_permutationhash[mode][hashindex] = p;
1385         //if (hashdepth > 10)
1386         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1387         return p;
1388 }
1389
1390 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1391 {
1392         char *shaderstring;
1393         if (!filename || !filename[0])
1394                 return NULL;
1395         if (!strcmp(filename, "hlsl/default.hlsl"))
1396         {
1397                 if (!hlslshaderstring)
1398                 {
1399                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1400                         if (hlslshaderstring)
1401                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1402                         else
1403                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1404                 }
1405                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1406                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1407                 return shaderstring;
1408         }
1409         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1410         if (shaderstring)
1411         {
1412                 if (printfromdisknotice)
1413                         Con_DPrintf("from disk %s... ", filename);
1414                 return shaderstring;
1415         }
1416         return shaderstring;
1417 }
1418
1419 #include <d3dx9.h>
1420 //#include <d3dx9shader.h>
1421 //#include <d3dx9mesh.h>
1422
1423 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1424 {
1425         DWORD *vsbin = NULL;
1426         DWORD *psbin = NULL;
1427         fs_offset_t vsbinsize;
1428         fs_offset_t psbinsize;
1429 //      IDirect3DVertexShader9 *vs = NULL;
1430 //      IDirect3DPixelShader9 *ps = NULL;
1431         ID3DXBuffer *vslog = NULL;
1432         ID3DXBuffer *vsbuffer = NULL;
1433         ID3DXConstantTable *vsconstanttable = NULL;
1434         ID3DXBuffer *pslog = NULL;
1435         ID3DXBuffer *psbuffer = NULL;
1436         ID3DXConstantTable *psconstanttable = NULL;
1437         int vsresult = 0;
1438         int psresult = 0;
1439         char temp[MAX_INPUTLINE];
1440         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1441         qboolean debugshader = gl_paranoid.integer != 0;
1442         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1443         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1444         if (!debugshader)
1445         {
1446                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1447                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1448         }
1449         if ((!vsbin && vertstring) || (!psbin && fragstring))
1450         {
1451                 const char* dllnames_d3dx9 [] =
1452                 {
1453                         "d3dx9_43.dll",
1454                         "d3dx9_42.dll",
1455                         "d3dx9_41.dll",
1456                         "d3dx9_40.dll",
1457                         "d3dx9_39.dll",
1458                         "d3dx9_38.dll",
1459                         "d3dx9_37.dll",
1460                         "d3dx9_36.dll",
1461                         "d3dx9_35.dll",
1462                         "d3dx9_34.dll",
1463                         "d3dx9_33.dll",
1464                         "d3dx9_32.dll",
1465                         "d3dx9_31.dll",
1466                         "d3dx9_30.dll",
1467                         "d3dx9_29.dll",
1468                         "d3dx9_28.dll",
1469                         "d3dx9_27.dll",
1470                         "d3dx9_26.dll",
1471                         "d3dx9_25.dll",
1472                         "d3dx9_24.dll",
1473                         NULL
1474                 };
1475                 dllhandle_t d3dx9_dll = NULL;
1476                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1477                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1478                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1479                 dllfunction_t d3dx9_dllfuncs[] =
1480                 {
1481                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1482                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1483                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1484                         {NULL, NULL}
1485                 };
1486                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1487                 {
1488                         DWORD shaderflags = 0;
1489                         if (debugshader)
1490                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1491                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1492                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1493                         if (vertstring && vertstring[0])
1494                         {
1495                                 if (debugshader)
1496                                 {
1497 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1498 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1499                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1500                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1501                                 }
1502                                 else
1503                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1504                                 if (vsbuffer)
1505                                 {
1506                                         vsbinsize = vsbuffer->GetBufferSize();
1507                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1508                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1509                                         vsbuffer->Release();
1510                                 }
1511                                 if (vslog)
1512                                 {
1513                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1514                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1515                                         vslog->Release();
1516                                 }
1517                         }
1518                         if (fragstring && fragstring[0])
1519                         {
1520                                 if (debugshader)
1521                                 {
1522 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1523 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1524                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1525                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1526                                 }
1527                                 else
1528                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1529                                 if (psbuffer)
1530                                 {
1531                                         psbinsize = psbuffer->GetBufferSize();
1532                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1533                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1534                                         psbuffer->Release();
1535                                 }
1536                                 if (pslog)
1537                                 {
1538                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1539                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1540                                         pslog->Release();
1541                                 }
1542                         }
1543                         Sys_UnloadLibrary(&d3dx9_dll);
1544                 }
1545                 else
1546                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1547         }
1548         if (vsbin && psbin)
1549         {
1550                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1551                 if (FAILED(vsresult))
1552                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1553                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1554                 if (FAILED(psresult))
1555                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1556         }
1557         // free the shader data
1558         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1559         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1560 }
1561
1562 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1563 {
1564         int i;
1565         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1566         int vertstring_length = 0;
1567         int geomstring_length = 0;
1568         int fragstring_length = 0;
1569         char *t;
1570         char *vertexstring, *geometrystring, *fragmentstring;
1571         char *vertstring, *geomstring, *fragstring;
1572         char permutationname[256];
1573         char cachename[256];
1574         int vertstrings_count = 0;
1575         int geomstrings_count = 0;
1576         int fragstrings_count = 0;
1577         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1578         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1579         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1580
1581         if (p->compiled)
1582                 return;
1583         p->compiled = true;
1584         p->vertexshader = NULL;
1585         p->pixelshader = NULL;
1586
1587         permutationname[0] = 0;
1588         cachename[0] = 0;
1589         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1590         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1591         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1592
1593         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1594         strlcat(cachename, "hlsl/", sizeof(cachename));
1595
1596         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1597         vertstrings_count = 0;
1598         geomstrings_count = 0;
1599         fragstrings_count = 0;
1600         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1601         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1602         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1603
1604         // the first pretext is which type of shader to compile as
1605         // (later these will all be bound together as a program object)
1606         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1607         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1608         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1609
1610         // the second pretext is the mode (for example a light source)
1611         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1612         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1613         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1614         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1615         strlcat(cachename, modeinfo->name, sizeof(cachename));
1616
1617         // now add all the permutation pretexts
1618         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1619         {
1620                 if (permutation & (1<<i))
1621                 {
1622                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1623                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1624                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1625                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1626                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1627                 }
1628                 else
1629                 {
1630                         // keep line numbers correct
1631                         vertstrings_list[vertstrings_count++] = "\n";
1632                         geomstrings_list[geomstrings_count++] = "\n";
1633                         fragstrings_list[fragstrings_count++] = "\n";
1634                 }
1635         }
1636
1637         // add static parms
1638         R_CompileShader_AddStaticParms(mode, permutation);
1639         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1640         vertstrings_count += shaderstaticparms_count;
1641         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1642         geomstrings_count += shaderstaticparms_count;
1643         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1644         fragstrings_count += shaderstaticparms_count;
1645
1646         // replace spaces in the cachename with _ characters
1647         for (i = 0;cachename[i];i++)
1648                 if (cachename[i] == ' ')
1649                         cachename[i] = '_';
1650
1651         // now append the shader text itself
1652         vertstrings_list[vertstrings_count++] = vertexstring;
1653         geomstrings_list[geomstrings_count++] = geometrystring;
1654         fragstrings_list[fragstrings_count++] = fragmentstring;
1655
1656         // if any sources were NULL, clear the respective list
1657         if (!vertexstring)
1658                 vertstrings_count = 0;
1659         if (!geometrystring)
1660                 geomstrings_count = 0;
1661         if (!fragmentstring)
1662                 fragstrings_count = 0;
1663
1664         vertstring_length = 0;
1665         for (i = 0;i < vertstrings_count;i++)
1666                 vertstring_length += strlen(vertstrings_list[i]);
1667         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1668         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1669                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1670
1671         geomstring_length = 0;
1672         for (i = 0;i < geomstrings_count;i++)
1673                 geomstring_length += strlen(geomstrings_list[i]);
1674         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1675         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1676                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1677
1678         fragstring_length = 0;
1679         for (i = 0;i < fragstrings_count;i++)
1680                 fragstring_length += strlen(fragstrings_list[i]);
1681         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1682         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1683                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1684
1685         // try to load the cached shader, or generate one
1686         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1687
1688         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1689                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1690         else
1691                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1692
1693         // free the strings
1694         if (vertstring)
1695                 Mem_Free(vertstring);
1696         if (geomstring)
1697                 Mem_Free(geomstring);
1698         if (fragstring)
1699                 Mem_Free(fragstring);
1700         if (vertexstring)
1701                 Mem_Free(vertexstring);
1702         if (geometrystring)
1703                 Mem_Free(geometrystring);
1704         if (fragmentstring)
1705                 Mem_Free(fragmentstring);
1706 }
1707
1708 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1709 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1710 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);}
1711 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);}
1712 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);}
1713 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);}
1714
1715 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1716 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1717 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);}
1718 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);}
1719 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);}
1720 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);}
1721
1722 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1723 {
1724         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1725         if (r_hlsl_permutation != perm)
1726         {
1727                 r_hlsl_permutation = perm;
1728                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1729                 {
1730                         if (!r_hlsl_permutation->compiled)
1731                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1732                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1733                         {
1734                                 // remove features until we find a valid permutation
1735                                 int i;
1736                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1737                                 {
1738                                         // reduce i more quickly whenever it would not remove any bits
1739                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1740                                         if (!(permutation & j))
1741                                                 continue;
1742                                         permutation -= j;
1743                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1744                                         if (!r_hlsl_permutation->compiled)
1745                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1746                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1747                                                 break;
1748                                 }
1749                                 if (i >= SHADERPERMUTATION_COUNT)
1750                                 {
1751                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1752                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1753                                         return; // no bit left to clear, entire mode is broken
1754                                 }
1755                         }
1756                 }
1757                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1758                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1759         }
1760         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1761         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1762         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1763 }
1764 #endif
1765
1766 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1767 {
1768         DPSOFTRAST_SetShader(mode, permutation);
1769         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1770         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1771         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1772 }
1773
1774 void R_GLSL_Restart_f(void)
1775 {
1776         unsigned int i, limit;
1777         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1778                 Mem_Free(glslshaderstring);
1779         glslshaderstring = NULL;
1780         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1781                 Mem_Free(hlslshaderstring);
1782         hlslshaderstring = NULL;
1783         switch(vid.renderpath)
1784         {
1785         case RENDERPATH_D3D9:
1786 #ifdef SUPPORTD3D
1787                 {
1788                         r_hlsl_permutation_t *p;
1789                         r_hlsl_permutation = NULL;
1790                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1791                         for (i = 0;i < limit;i++)
1792                         {
1793                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1794                                 {
1795                                         if (p->vertexshader)
1796                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1797                                         if (p->pixelshader)
1798                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1799                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1800                                 }
1801                         }
1802                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1803                 }
1804 #endif
1805                 break;
1806         case RENDERPATH_D3D10:
1807                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1808                 break;
1809         case RENDERPATH_D3D11:
1810                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1811                 break;
1812         case RENDERPATH_GL20:
1813         case RENDERPATH_GLES2:
1814                 {
1815                         r_glsl_permutation_t *p;
1816                         r_glsl_permutation = NULL;
1817                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1818                         for (i = 0;i < limit;i++)
1819                         {
1820                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1821                                 {
1822                                         GL_Backend_FreeProgram(p->program);
1823                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1824                                 }
1825                         }
1826                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1827                 }
1828                 break;
1829         case RENDERPATH_GL13:
1830         case RENDERPATH_GL11:
1831                 break;
1832         case RENDERPATH_SOFT:
1833                 break;
1834         }
1835 }
1836
1837 void R_GLSL_DumpShader_f(void)
1838 {
1839         int i;
1840         qfile_t *file;
1841
1842         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1843         if (file)
1844         {
1845                 FS_Print(file, "/* The engine may define the following macros:\n");
1846                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1847                 for (i = 0;i < SHADERMODE_COUNT;i++)
1848                         FS_Print(file, glslshadermodeinfo[i].pretext);
1849                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1850                         FS_Print(file, shaderpermutationinfo[i].pretext);
1851                 FS_Print(file, "*/\n");
1852                 FS_Print(file, builtinshaderstring);
1853                 FS_Close(file);
1854                 Con_Printf("glsl/default.glsl written\n");
1855         }
1856         else
1857                 Con_Printf("failed to write to glsl/default.glsl\n");
1858
1859         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1860         if (file)
1861         {
1862                 FS_Print(file, "/* The engine may define the following macros:\n");
1863                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1864                 for (i = 0;i < SHADERMODE_COUNT;i++)
1865                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1866                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1867                         FS_Print(file, shaderpermutationinfo[i].pretext);
1868                 FS_Print(file, "*/\n");
1869                 FS_Print(file, builtinhlslshaderstring);
1870                 FS_Close(file);
1871                 Con_Printf("hlsl/default.hlsl written\n");
1872         }
1873         else
1874                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1875 }
1876
1877 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1878 {
1879         if (!second)
1880                 texturemode = GL_MODULATE;
1881         switch (vid.renderpath)
1882         {
1883         case RENDERPATH_D3D9:
1884 #ifdef SUPPORTD3D
1885                 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))));
1886                 R_Mesh_TexBind(GL20TU_FIRST , first );
1887                 R_Mesh_TexBind(GL20TU_SECOND, second);
1888 #endif
1889                 break;
1890         case RENDERPATH_D3D10:
1891                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1892                 break;
1893         case RENDERPATH_D3D11:
1894                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1895                 break;
1896         case RENDERPATH_GL20:
1897         case RENDERPATH_GLES2:
1898                 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))));
1899                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1900                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1901                 break;
1902         case RENDERPATH_GL13:
1903                 R_Mesh_TexBind(0, first );
1904                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1905                 R_Mesh_TexBind(1, second);
1906                 if (second)
1907                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1908                 break;
1909         case RENDERPATH_GL11:
1910                 R_Mesh_TexBind(0, first );
1911                 break;
1912         case RENDERPATH_SOFT:
1913                 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))));
1914                 R_Mesh_TexBind(GL20TU_FIRST , first );
1915                 R_Mesh_TexBind(GL20TU_SECOND, second);
1916                 break;
1917         }
1918 }
1919
1920 void R_SetupShader_DepthOrShadow(void)
1921 {
1922         switch (vid.renderpath)
1923         {
1924         case RENDERPATH_D3D9:
1925 #ifdef SUPPORTD3D
1926                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1927 #endif
1928                 break;
1929         case RENDERPATH_D3D10:
1930                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931                 break;
1932         case RENDERPATH_D3D11:
1933                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1934                 break;
1935         case RENDERPATH_GL20:
1936         case RENDERPATH_GLES2:
1937                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1938                 break;
1939         case RENDERPATH_GL13:
1940                 R_Mesh_TexBind(0, 0);
1941                 R_Mesh_TexBind(1, 0);
1942                 break;
1943         case RENDERPATH_GL11:
1944                 R_Mesh_TexBind(0, 0);
1945                 break;
1946         case RENDERPATH_SOFT:
1947                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1948                 break;
1949         }
1950 }
1951
1952 void R_SetupShader_ShowDepth(void)
1953 {
1954         switch (vid.renderpath)
1955         {
1956         case RENDERPATH_D3D9:
1957 #ifdef SUPPORTHLSL
1958                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1959 #endif
1960                 break;
1961         case RENDERPATH_D3D10:
1962                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1963                 break;
1964         case RENDERPATH_D3D11:
1965                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1966                 break;
1967         case RENDERPATH_GL20:
1968         case RENDERPATH_GLES2:
1969                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1970                 break;
1971         case RENDERPATH_GL13:
1972                 break;
1973         case RENDERPATH_GL11:
1974                 break;
1975         case RENDERPATH_SOFT:
1976                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1977                 break;
1978         }
1979 }
1980
1981 extern qboolean r_shadow_usingdeferredprepass;
1982 extern cvar_t r_shadow_deferred_8bitrange;
1983 extern rtexture_t *r_shadow_attenuationgradienttexture;
1984 extern rtexture_t *r_shadow_attenuation2dtexture;
1985 extern rtexture_t *r_shadow_attenuation3dtexture;
1986 extern qboolean r_shadow_usingshadowmap2d;
1987 extern qboolean r_shadow_usingshadowmaportho;
1988 extern float r_shadow_shadowmap_texturescale[2];
1989 extern float r_shadow_shadowmap_parameters[4];
1990 extern qboolean r_shadow_shadowmapvsdct;
1991 extern qboolean r_shadow_shadowmapsampler;
1992 extern int r_shadow_shadowmappcf;
1993 extern rtexture_t *r_shadow_shadowmap2dtexture;
1994 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1995 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1996 extern matrix4x4_t r_shadow_shadowmapmatrix;
1997 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1998 extern int r_shadow_prepass_width;
1999 extern int r_shadow_prepass_height;
2000 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2001 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2002 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2003 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2004 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2005
2006 #define BLENDFUNC_ALLOWS_COLORMOD      1
2007 #define BLENDFUNC_ALLOWS_FOG           2
2008 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2009 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2010 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2011 static int R_BlendFuncFlags(int src, int dst)
2012 {
2013         int r = 0;
2014
2015         // a blendfunc allows colormod if:
2016         // a) it can never keep the destination pixel invariant, or
2017         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2018         // this is to prevent unintended side effects from colormod
2019
2020         // a blendfunc allows fog if:
2021         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2022         // this is to prevent unintended side effects from fog
2023
2024         // these checks are the output of fogeval.pl
2025
2026         r |= BLENDFUNC_ALLOWS_COLORMOD;
2027         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2028         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2029         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2030         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2031         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2032         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2033         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2034         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2036         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2037         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2038         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2039         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2040         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2041         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2042         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2043         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2044         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2045         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2046         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2047         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2048
2049         return r;
2050 }
2051
2052 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)
2053 {
2054         // select a permutation of the lighting shader appropriate to this
2055         // combination of texture, entity, light source, and fogging, only use the
2056         // minimum features necessary to avoid wasting rendering time in the
2057         // fragment shader on features that are not being used
2058         unsigned int permutation = 0;
2059         unsigned int mode = 0;
2060         int blendfuncflags;
2061         static float dummy_colormod[3] = {1, 1, 1};
2062         float *colormod = rsurface.colormod;
2063         float m16f[16];
2064         matrix4x4_t tempmatrix;
2065         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2066         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2067                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2068         if (rsurfacepass == RSURFPASS_BACKGROUND)
2069         {
2070                 // distorted background
2071                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2072                 {
2073                         mode = SHADERMODE_WATER;
2074                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2075                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2076                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2077                         {
2078                                 // this is the right thing to do for wateralpha
2079                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2080                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2081                         }
2082                         else
2083                         {
2084                                 // this is the right thing to do for entity alpha
2085                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2086                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2087                         }
2088                 }
2089                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2090                 {
2091                         mode = SHADERMODE_REFRACTION;
2092                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2093                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2094                 }
2095                 else
2096                 {
2097                         mode = SHADERMODE_GENERIC;
2098                         permutation |= SHADERPERMUTATION_DIFFUSE;
2099                         GL_BlendFunc(GL_ONE, GL_ZERO);
2100                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2101                 }
2102         }
2103         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2104         {
2105                 if (r_glsl_offsetmapping.integer)
2106                 {
2107                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2108                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2109                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2110                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2111                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2112                         {
2113                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2114                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2115                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2116                         }
2117                 }
2118                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2119                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2120                 // normalmap (deferred prepass), may use alpha test on diffuse
2121                 mode = SHADERMODE_DEFERREDGEOMETRY;
2122                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2123                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2124                 GL_BlendFunc(GL_ONE, GL_ZERO);
2125                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2126         }
2127         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2128         {
2129                 if (r_glsl_offsetmapping.integer)
2130                 {
2131                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2132                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2133                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2134                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2135                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2136                         {
2137                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2138                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2139                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2140                         }
2141                 }
2142                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2143                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2144                 // light source
2145                 mode = SHADERMODE_LIGHTSOURCE;
2146                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2147                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2148                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2149                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2150                 if (diffusescale > 0)
2151                         permutation |= SHADERPERMUTATION_DIFFUSE;
2152                 if (specularscale > 0)
2153                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2154                 if (r_refdef.fogenabled)
2155                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2156                 if (rsurface.texture->colormapping)
2157                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2158                 if (r_shadow_usingshadowmap2d)
2159                 {
2160                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2161                         if(r_shadow_shadowmapvsdct)
2162                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2163
2164                         if (r_shadow_shadowmapsampler)
2165                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2166                         if (r_shadow_shadowmappcf > 1)
2167                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2168                         else if (r_shadow_shadowmappcf)
2169                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2170                 }
2171                 if (rsurface.texture->reflectmasktexture)
2172                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2173                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2174                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2175         }
2176         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2177         {
2178                 if (r_glsl_offsetmapping.integer)
2179                 {
2180                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2181                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2182                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2183                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2184                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2185                         {
2186                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2187                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2188                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2189                         }
2190                 }
2191                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2192                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2193                 // unshaded geometry (fullbright or ambient model lighting)
2194                 mode = SHADERMODE_FLATCOLOR;
2195                 ambientscale = diffusescale = specularscale = 0;
2196                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2197                         permutation |= SHADERPERMUTATION_GLOW;
2198                 if (r_refdef.fogenabled)
2199                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2200                 if (rsurface.texture->colormapping)
2201                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2202                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2203                 {
2204                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2205                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2206
2207                         if (r_shadow_shadowmapsampler)
2208                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2209                         if (r_shadow_shadowmappcf > 1)
2210                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2211                         else if (r_shadow_shadowmappcf)
2212                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2213                 }
2214                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2215                         permutation |= SHADERPERMUTATION_REFLECTION;
2216                 if (rsurface.texture->reflectmasktexture)
2217                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2218                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2219                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2220         }
2221         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2222         {
2223                 if (r_glsl_offsetmapping.integer)
2224                 {
2225                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2226                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2227                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2228                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2229                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2230                         {
2231                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2232                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2233                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2234                         }
2235                 }
2236                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2237                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2238                 // directional model lighting
2239                 mode = SHADERMODE_LIGHTDIRECTION;
2240                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2241                         permutation |= SHADERPERMUTATION_GLOW;
2242                 permutation |= SHADERPERMUTATION_DIFFUSE;
2243                 if (specularscale > 0)
2244                         permutation |= SHADERPERMUTATION_SPECULAR;
2245                 if (r_refdef.fogenabled)
2246                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2247                 if (rsurface.texture->colormapping)
2248                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2249                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2250                 {
2251                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2252                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2253
2254                         if (r_shadow_shadowmapsampler)
2255                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2256                         if (r_shadow_shadowmappcf > 1)
2257                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2258                         else if (r_shadow_shadowmappcf)
2259                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2260                 }
2261                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2262                         permutation |= SHADERPERMUTATION_REFLECTION;
2263                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2264                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2265                 if (rsurface.texture->reflectmasktexture)
2266                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2267                 if (r_shadow_bouncegridtexture)
2268                 {
2269                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2270                         if (r_shadow_bouncegriddirectional)
2271                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2272                 }
2273                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2274                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2275         }
2276         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2277         {
2278                 if (r_glsl_offsetmapping.integer)
2279                 {
2280                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2281                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2282                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2283                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2284                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2285                         {
2286                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2287                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2288                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2289                         }
2290                 }
2291                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2292                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2293                 // ambient model lighting
2294                 mode = SHADERMODE_LIGHTDIRECTION;
2295                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2296                         permutation |= SHADERPERMUTATION_GLOW;
2297                 if (r_refdef.fogenabled)
2298                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2299                 if (rsurface.texture->colormapping)
2300                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2301                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2302                 {
2303                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2304                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2305
2306                         if (r_shadow_shadowmapsampler)
2307                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2308                         if (r_shadow_shadowmappcf > 1)
2309                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2310                         else if (r_shadow_shadowmappcf)
2311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2312                 }
2313                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2314                         permutation |= SHADERPERMUTATION_REFLECTION;
2315                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2316                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2317                 if (rsurface.texture->reflectmasktexture)
2318                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2319                 if (r_shadow_bouncegridtexture)
2320                 {
2321                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2322                         if (r_shadow_bouncegriddirectional)
2323                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2324                 }
2325                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2326                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327         }
2328         else
2329         {
2330                 if (r_glsl_offsetmapping.integer)
2331                 {
2332                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2333                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2334                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2335                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2336                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2337                         {
2338                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2339                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2340                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2341                         }
2342                 }
2343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2344                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2345                 // lightmapped wall
2346                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2347                         permutation |= SHADERPERMUTATION_GLOW;
2348                 if (r_refdef.fogenabled)
2349                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2350                 if (rsurface.texture->colormapping)
2351                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2352                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2353                 {
2354                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2355                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2356
2357                         if (r_shadow_shadowmapsampler)
2358                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2359                         if (r_shadow_shadowmappcf > 1)
2360                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2361                         else if (r_shadow_shadowmappcf)
2362                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2363                 }
2364                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2365                         permutation |= SHADERPERMUTATION_REFLECTION;
2366                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2367                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2368                 if (rsurface.texture->reflectmasktexture)
2369                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2370                 if (FAKELIGHT_ENABLED)
2371                 {
2372                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2373                         mode = SHADERMODE_FAKELIGHT;
2374                         permutation |= SHADERPERMUTATION_DIFFUSE;
2375                         if (specularscale > 0)
2376                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2377                 }
2378                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2379                 {
2380                         // deluxemapping (light direction texture)
2381                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2382                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2383                         else
2384                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2385                         permutation |= SHADERPERMUTATION_DIFFUSE;
2386                         if (specularscale > 0)
2387                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2388                 }
2389                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2390                 {
2391                         // fake deluxemapping (uniform light direction in tangentspace)
2392                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2393                         permutation |= SHADERPERMUTATION_DIFFUSE;
2394                         if (specularscale > 0)
2395                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2396                 }
2397                 else if (rsurface.uselightmaptexture)
2398                 {
2399                         // ordinary lightmapping (q1bsp, q3bsp)
2400                         mode = SHADERMODE_LIGHTMAP;
2401                 }
2402                 else
2403                 {
2404                         // ordinary vertex coloring (q3bsp)
2405                         mode = SHADERMODE_VERTEXCOLOR;
2406                 }
2407                 if (r_shadow_bouncegridtexture)
2408                 {
2409                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2410                         if (r_shadow_bouncegriddirectional)
2411                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2412                 }
2413                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415         }
2416         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2417                 colormod = dummy_colormod;
2418         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2419                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2420         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2421                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2422         switch(vid.renderpath)
2423         {
2424         case RENDERPATH_D3D9:
2425 #ifdef SUPPORTD3D
2426                 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);
2427                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2428                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2429                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2430                 if (mode == SHADERMODE_LIGHTSOURCE)
2431                 {
2432                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2433                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2434                 }
2435                 else
2436                 {
2437                         if (mode == SHADERMODE_LIGHTDIRECTION)
2438                         {
2439                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2440                         }
2441                 }
2442                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2443                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2444                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2445                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2446                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2447
2448                 if (mode == SHADERMODE_LIGHTSOURCE)
2449                 {
2450                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2451                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2452                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2453                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2454                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2455
2456                         // additive passes are only darkened by fog, not tinted
2457                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2458                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2459                 }
2460                 else
2461                 {
2462                         if (mode == SHADERMODE_FLATCOLOR)
2463                         {
2464                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2465                         }
2466                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2467                         {
2468                                 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]);
2469                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2470                                 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);
2471                                 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);
2472                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2473                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2474                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2475                         }
2476                         else
2477                         {
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2480                                 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);
2481                                 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);
2482                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2483                         }
2484                         // additive passes are only darkened by fog, not tinted
2485                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2487                         else
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2489                         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);
2490                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2491                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2492                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2493                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2494                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2495                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2496                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2497                         if (mode == SHADERMODE_WATER)
2498                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2499                 }
2500                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2501                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2502                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2503                 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));
2504                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2505                 if (rsurface.texture->pantstexture)
2506                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2507                 else
2508                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2509                 if (rsurface.texture->shirttexture)
2510                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2511                 else
2512                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2513                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2514                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2515                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2516                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2517                 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2518                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2519                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2520
2521                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2522                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2523                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2524                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2525                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2526                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2527                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2528                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2529                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2530                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2531                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2532                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2533                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2534                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2535                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2536                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2537                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2538                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2539                 {
2540                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2541                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2542                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2543                 }
2544                 else
2545                 {
2546                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2547                 }
2548 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2549 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2550                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2551                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2552                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2553                 {
2554                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2555                         if (rsurface.rtlight)
2556                         {
2557                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2558                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2559                         }
2560                 }
2561 #endif
2562                 break;
2563         case RENDERPATH_D3D10:
2564                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2565                 break;
2566         case RENDERPATH_D3D11:
2567                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2568                 break;
2569         case RENDERPATH_GL20:
2570         case RENDERPATH_GLES2:
2571                 if (!vid.useinterleavedarrays)
2572                 {
2573                         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);
2574                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2575                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2576                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2577                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2578                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2579                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2580                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2581                 }
2582                 else
2583                 {
2584                         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);
2585                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2586                 }
2587                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2588                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2589                 if (mode == SHADERMODE_LIGHTSOURCE)
2590                 {
2591                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2592                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2593                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2594                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2595                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2596                         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);
2597         
2598                         // additive passes are only darkened by fog, not tinted
2599                         if (r_glsl_permutation->loc_FogColor >= 0)
2600                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2601                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2602                 }
2603                 else
2604                 {
2605                         if (mode == SHADERMODE_FLATCOLOR)
2606                         {
2607                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2608                         }
2609                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2610                         {
2611                                 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]);
2612                                 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]);
2613                                 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);
2614                                 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);
2615                                 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);
2616                                 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]);
2617                                 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]);
2618                         }
2619                         else
2620                         {
2621                                 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]);
2622                                 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]);
2623                                 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);
2624                                 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);
2625                                 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);
2626                         }
2627                         // additive passes are only darkened by fog, not tinted
2628                         if (r_glsl_permutation->loc_FogColor >= 0)
2629                         {
2630                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2631                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2632                                 else
2633                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2634                         }
2635                         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);
2636                         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]);
2637                         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]);
2638                         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]);
2639                         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]);
2640                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2641                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2642                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2643                         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]);
2644                 }
2645                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2646                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2647                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2648                 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]);
2649                 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]);
2650
2651                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2652                 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));
2653                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2654                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2655                 {
2656                         if (rsurface.texture->pantstexture)
2657                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2658                         else
2659                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2660                 }
2661                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2662                 {
2663                         if (rsurface.texture->shirttexture)
2664                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2665                         else
2666                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2667                 }
2668                 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]);
2669                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2670                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2671                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2672                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2673                 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]);
2674                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2675                 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);}
2676                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2677
2678                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2679                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2680                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2681                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2682                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2683                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2684                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2685                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2686                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2687                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2688                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2689                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2690                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2691                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2692                 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);
2693                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2694                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2695                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2696                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2697                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2698                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2699                 {
2700                         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);
2701                         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);
2702                         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);
2703                 }
2704                 else
2705                 {
2706                         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);
2707                 }
2708                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2709                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2710                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2711                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2712                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2713                 {
2714                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2715                         if (rsurface.rtlight)
2716                         {
2717                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2718                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2719                         }
2720                 }
2721                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2722                 CHECKGLERROR
2723                 break;
2724         case RENDERPATH_GL13:
2725         case RENDERPATH_GL11:
2726                 break;
2727         case RENDERPATH_SOFT:
2728                 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);
2729                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2730                 R_SetupShader_SetPermutationSoft(mode, permutation);
2731                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2732                 if (mode == SHADERMODE_LIGHTSOURCE)
2733                 {
2734                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2735                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2736                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2737                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2738                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2739                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2740         
2741                         // additive passes are only darkened by fog, not tinted
2742                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2743                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2744                 }
2745                 else
2746                 {
2747                         if (mode == SHADERMODE_FLATCOLOR)
2748                         {
2749                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2750                         }
2751                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2752                         {
2753                                 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]);
2754                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2755                                 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);
2756                                 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);
2757                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2758                                 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]);
2759                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2760                         }
2761                         else
2762                         {
2763                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2764                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2765                                 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);
2766                                 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);
2767                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2768                         }
2769                         // additive passes are only darkened by fog, not tinted
2770                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2772                         else
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2774                         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);
2775                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2776                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2777                         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]);
2778                         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]);
2779                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2780                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2781                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2782                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2783                 }
2784                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2785                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2786                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2787                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2788                 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]);
2789
2790                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2791                 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));
2792                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2793                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2794                 {
2795                         if (rsurface.texture->pantstexture)
2796                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2797                         else
2798                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2799                 }
2800                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2801                 {
2802                         if (rsurface.texture->shirttexture)
2803                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2804                         else
2805                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2806                 }
2807                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2808                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2809                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2810                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2811                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2812                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2813                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2814
2815                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2816                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2817                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2818                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2819                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2820                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2821                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2822                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2823                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2824                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2825                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2826                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2827                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2828                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2829                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2830                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2831                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2832                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2833                 {
2834                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2835                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2836                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2837                 }
2838                 else
2839                 {
2840                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2841                 }
2842 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2843 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2844                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2845                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2846                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2847                 {
2848                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2849                         if (rsurface.rtlight)
2850                         {
2851                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2852                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2853                         }
2854                 }
2855                 break;
2856         }
2857 }
2858
2859 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2860 {
2861         // select a permutation of the lighting shader appropriate to this
2862         // combination of texture, entity, light source, and fogging, only use the
2863         // minimum features necessary to avoid wasting rendering time in the
2864         // fragment shader on features that are not being used
2865         unsigned int permutation = 0;
2866         unsigned int mode = 0;
2867         const float *lightcolorbase = rtlight->currentcolor;
2868         float ambientscale = rtlight->ambientscale;
2869         float diffusescale = rtlight->diffusescale;
2870         float specularscale = rtlight->specularscale;
2871         // this is the location of the light in view space
2872         vec3_t viewlightorigin;
2873         // this transforms from view space (camera) to light space (cubemap)
2874         matrix4x4_t viewtolight;
2875         matrix4x4_t lighttoview;
2876         float viewtolight16f[16];
2877         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2878         // light source
2879         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2880         if (rtlight->currentcubemap != r_texture_whitecube)
2881                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2882         if (diffusescale > 0)
2883                 permutation |= SHADERPERMUTATION_DIFFUSE;
2884         if (specularscale > 0)
2885                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2886         if (r_shadow_usingshadowmap2d)
2887         {
2888                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2889                 if (r_shadow_shadowmapvsdct)
2890                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2891
2892                 if (r_shadow_shadowmapsampler)
2893                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2894                 if (r_shadow_shadowmappcf > 1)
2895                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2896                 else if (r_shadow_shadowmappcf)
2897                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2898         }
2899         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2900         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2901         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2902         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2903         switch(vid.renderpath)
2904         {
2905         case RENDERPATH_D3D9:
2906 #ifdef SUPPORTD3D
2907                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2908                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2909                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2910                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2911                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2912                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2913                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2914                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2915                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2916                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2917                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2918
2919                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2920                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2921                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2922                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2923                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2924                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2925 #endif
2926                 break;
2927         case RENDERPATH_D3D10:
2928                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2929                 break;
2930         case RENDERPATH_D3D11:
2931                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2932                 break;
2933         case RENDERPATH_GL20:
2934         case RENDERPATH_GLES2:
2935                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2936                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2937                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2938                 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);
2939                 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);
2940                 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);
2941                 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]);
2942                 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]);
2943                 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));
2944                 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]);
2945                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2946
2947                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2948                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2949                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2950                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2951                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2952                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2953                 break;
2954         case RENDERPATH_GL13:
2955         case RENDERPATH_GL11:
2956                 break;
2957         case RENDERPATH_SOFT:
2958                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2959                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2961                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2962                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2963                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2964                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2965                 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]);
2966                 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));
2967                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2969
2970                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2971                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2972                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2973                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2974                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2975                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2976                 break;
2977         }
2978 }
2979
2980 #define SKINFRAME_HASH 1024
2981
2982 typedef struct
2983 {
2984         int loadsequence; // incremented each level change
2985         memexpandablearray_t array;
2986         skinframe_t *hash[SKINFRAME_HASH];
2987 }
2988 r_skinframe_t;
2989 r_skinframe_t r_skinframe;
2990
2991 void R_SkinFrame_PrepareForPurge(void)
2992 {
2993         r_skinframe.loadsequence++;
2994         // wrap it without hitting zero
2995         if (r_skinframe.loadsequence >= 200)
2996                 r_skinframe.loadsequence = 1;
2997 }
2998
2999 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3000 {
3001         if (!skinframe)
3002                 return;
3003         // mark the skinframe as used for the purging code
3004         skinframe->loadsequence = r_skinframe.loadsequence;
3005 }
3006
3007 void R_SkinFrame_Purge(void)
3008 {
3009         int i;
3010         skinframe_t *s;
3011         for (i = 0;i < SKINFRAME_HASH;i++)
3012         {
3013                 for (s = r_skinframe.hash[i];s;s = s->next)
3014                 {
3015                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3016                         {
3017                                 if (s->merged == s->base)
3018                                         s->merged = NULL;
3019                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3020                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3021                                 R_PurgeTexture(s->merged);s->merged = NULL;
3022                                 R_PurgeTexture(s->base  );s->base   = NULL;
3023                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3024                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3025                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3026                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3027                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3028                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3029                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3030                                 s->loadsequence = 0;
3031                         }
3032                 }
3033         }
3034 }
3035
3036 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3037         skinframe_t *item;
3038         char basename[MAX_QPATH];
3039
3040         Image_StripImageExtension(name, basename, sizeof(basename));
3041
3042         if( last == NULL ) {
3043                 int hashindex;
3044                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3045                 item = r_skinframe.hash[hashindex];
3046         } else {
3047                 item = last->next;
3048         }
3049
3050         // linearly search through the hash bucket
3051         for( ; item ; item = item->next ) {
3052                 if( !strcmp( item->basename, basename ) ) {
3053                         return item;
3054                 }
3055         }
3056         return NULL;
3057 }
3058
3059 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3060 {
3061         skinframe_t *item;
3062         int hashindex;
3063         char basename[MAX_QPATH];
3064
3065         Image_StripImageExtension(name, basename, sizeof(basename));
3066
3067         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3069                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3070                         break;
3071
3072         if (!item) {
3073                 rtexture_t *dyntexture;
3074                 // check whether its a dynamic texture
3075                 dyntexture = CL_GetDynTexture( basename );
3076                 if (!add && !dyntexture)
3077                         return NULL;
3078                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3079                 memset(item, 0, sizeof(*item));
3080                 strlcpy(item->basename, basename, sizeof(item->basename));
3081                 item->base = dyntexture; // either NULL or dyntexture handle
3082                 item->textureflags = textureflags;
3083                 item->comparewidth = comparewidth;
3084                 item->compareheight = compareheight;
3085                 item->comparecrc = comparecrc;
3086                 item->next = r_skinframe.hash[hashindex];
3087                 r_skinframe.hash[hashindex] = item;
3088         }
3089         else if( item->base == NULL )
3090         {
3091                 rtexture_t *dyntexture;
3092                 // check whether its a dynamic texture
3093                 // 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]
3094                 dyntexture = CL_GetDynTexture( basename );
3095                 item->base = dyntexture; // either NULL or dyntexture handle
3096         }
3097
3098         R_SkinFrame_MarkUsed(item);
3099         return item;
3100 }
3101
3102 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3103         { \
3104                 unsigned long long avgcolor[5], wsum; \
3105                 int pix, comp, w; \
3106                 avgcolor[0] = 0; \
3107                 avgcolor[1] = 0; \
3108                 avgcolor[2] = 0; \
3109                 avgcolor[3] = 0; \
3110                 avgcolor[4] = 0; \
3111                 wsum = 0; \
3112                 for(pix = 0; pix < cnt; ++pix) \
3113                 { \
3114                         w = 0; \
3115                         for(comp = 0; comp < 3; ++comp) \
3116                                 w += getpixel; \
3117                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3118                         { \
3119                                 ++wsum; \
3120                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3121                                 w = getpixel; \
3122                                 for(comp = 0; comp < 3; ++comp) \
3123                                         avgcolor[comp] += getpixel * w; \
3124                                 avgcolor[3] += w; \
3125                         } \
3126                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3127                         avgcolor[4] += getpixel; \
3128                 } \
3129                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3130                         avgcolor[3] = 1; \
3131                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3132                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3133                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3134                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3135         }
3136
3137 extern cvar_t gl_picmip;
3138 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3139 {
3140         int j;
3141         unsigned char *pixels;
3142         unsigned char *bumppixels;
3143         unsigned char *basepixels = NULL;
3144         int basepixels_width = 0;
3145         int basepixels_height = 0;
3146         skinframe_t *skinframe;
3147         rtexture_t *ddsbase = NULL;
3148         qboolean ddshasalpha = false;
3149         float ddsavgcolor[4];
3150         char basename[MAX_QPATH];
3151         int miplevel = R_PicmipForFlags(textureflags);
3152         int savemiplevel = miplevel;
3153         int mymiplevel;
3154
3155         if (cls.state == ca_dedicated)
3156                 return NULL;
3157
3158         // return an existing skinframe if already loaded
3159         // if loading of the first image fails, don't make a new skinframe as it
3160         // would cause all future lookups of this to be missing
3161         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3162         if (skinframe && skinframe->base)
3163                 return skinframe;
3164
3165         Image_StripImageExtension(name, basename, sizeof(basename));
3166
3167         // check for DDS texture file first
3168         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3169         {
3170                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3171                 if (basepixels == NULL)
3172                         return NULL;
3173         }
3174
3175         // FIXME handle miplevel
3176
3177         if (developer_loading.integer)
3178                 Con_Printf("loading skin \"%s\"\n", name);
3179
3180         // we've got some pixels to store, so really allocate this new texture now
3181         if (!skinframe)
3182                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3183         skinframe->stain = NULL;
3184         skinframe->merged = NULL;
3185         skinframe->base = NULL;
3186         skinframe->pants = NULL;
3187         skinframe->shirt = NULL;
3188         skinframe->nmap = NULL;
3189         skinframe->gloss = NULL;
3190         skinframe->glow = NULL;
3191         skinframe->fog = NULL;
3192         skinframe->reflect = NULL;
3193         skinframe->hasalpha = false;
3194
3195         if (ddsbase)
3196         {
3197                 skinframe->base = ddsbase;
3198                 skinframe->hasalpha = ddshasalpha;
3199                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3200                 if (r_loadfog && skinframe->hasalpha)
3201                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3202                 //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]);
3203         }
3204         else
3205         {
3206                 basepixels_width = image_width;
3207                 basepixels_height = image_height;
3208                 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);
3209                 if (textureflags & TEXF_ALPHA)
3210                 {
3211                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3212                         {
3213                                 if (basepixels[j] < 255)
3214                                 {
3215                                         skinframe->hasalpha = true;
3216                                         break;
3217                                 }
3218                         }
3219                         if (r_loadfog && skinframe->hasalpha)
3220                         {
3221                                 // has transparent pixels
3222                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3223                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3224                                 {
3225                                         pixels[j+0] = 255;
3226                                         pixels[j+1] = 255;
3227                                         pixels[j+2] = 255;
3228                                         pixels[j+3] = basepixels[j+3];
3229                                 }
3230                                 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);
3231                                 Mem_Free(pixels);
3232                         }
3233                 }
3234                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3235                 //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]);
3236                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3237                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3238                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3239                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3240         }
3241
3242         if (r_loaddds)
3243         {
3244                 mymiplevel = savemiplevel;
3245                 if (r_loadnormalmap)
3246                         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);
3247                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3248                 if (r_loadgloss)
3249                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3250                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3251                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3252                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3253         }
3254
3255         // _norm is the name used by tenebrae and has been adopted as standard
3256         if (r_loadnormalmap && skinframe->nmap == NULL)
3257         {
3258                 mymiplevel = savemiplevel;
3259                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3260                 {
3261                         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);
3262                         Mem_Free(pixels);
3263                         pixels = NULL;
3264                 }
3265                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3266                 {
3267                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3268                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3269                         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);
3270                         Mem_Free(pixels);
3271                         Mem_Free(bumppixels);
3272                 }
3273                 else if (r_shadow_bumpscale_basetexture.value > 0)
3274                 {
3275                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3276                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3277                         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);
3278                         Mem_Free(pixels);
3279                 }
3280                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3281                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3282         }
3283
3284         // _luma is supported only for tenebrae compatibility
3285         // _glow is the preferred name
3286         mymiplevel = savemiplevel;
3287         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))))
3288         {
3289                 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);
3290                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3291                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3292                 Mem_Free(pixels);pixels = NULL;
3293         }
3294
3295         mymiplevel = savemiplevel;
3296         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3297         {
3298                 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);
3299                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3300                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3301                 Mem_Free(pixels);
3302                 pixels = NULL;
3303         }
3304
3305         mymiplevel = savemiplevel;
3306         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3307         {
3308                 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);
3309                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3310                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3311                 Mem_Free(pixels);
3312                 pixels = NULL;
3313         }
3314
3315         mymiplevel = savemiplevel;
3316         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3317         {
3318                 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);
3319                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3320                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3321                 Mem_Free(pixels);
3322                 pixels = NULL;
3323         }
3324
3325         mymiplevel = savemiplevel;
3326         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3327         {
3328                 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);
3329                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3330                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3331                 Mem_Free(pixels);
3332                 pixels = NULL;
3333         }
3334
3335         if (basepixels)
3336                 Mem_Free(basepixels);
3337
3338         return skinframe;
3339 }
3340
3341 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3342 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3343 {
3344         int i;
3345         unsigned char *temp1, *temp2;
3346         skinframe_t *skinframe;
3347
3348         if (cls.state == ca_dedicated)
3349                 return NULL;
3350
3351         // if already loaded just return it, otherwise make a new skinframe
3352         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3353         if (skinframe && skinframe->base)
3354                 return skinframe;
3355
3356         skinframe->stain = NULL;
3357         skinframe->merged = NULL;
3358         skinframe->base = NULL;
3359         skinframe->pants = NULL;
3360         skinframe->shirt = NULL;
3361         skinframe->nmap = NULL;
3362         skinframe->gloss = NULL;
3363         skinframe->glow = NULL;
3364         skinframe->fog = NULL;
3365         skinframe->reflect = NULL;
3366         skinframe->hasalpha = false;
3367
3368         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3369         if (!skindata)
3370                 return NULL;
3371
3372         if (developer_loading.integer)
3373                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3374
3375         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3376         {
3377                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3378                 temp2 = temp1 + width * height * 4;
3379                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3380                 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);
3381                 Mem_Free(temp1);
3382         }
3383         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3384         if (textureflags & TEXF_ALPHA)
3385         {
3386                 for (i = 3;i < width * height * 4;i += 4)
3387                 {
3388                         if (skindata[i] < 255)
3389                         {
3390                                 skinframe->hasalpha = true;
3391                                 break;
3392                         }
3393                 }
3394                 if (r_loadfog && skinframe->hasalpha)
3395                 {
3396                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3397                         memcpy(fogpixels, skindata, width * height * 4);
3398                         for (i = 0;i < width * height * 4;i += 4)
3399                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3400                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3401                         Mem_Free(fogpixels);
3402                 }
3403         }
3404
3405         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3406         //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]);
3407
3408         return skinframe;
3409 }
3410
3411 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3412 {
3413         int i;
3414         int featuresmask;
3415         skinframe_t *skinframe;
3416
3417         if (cls.state == ca_dedicated)
3418                 return NULL;
3419
3420         // if already loaded just return it, otherwise make a new skinframe
3421         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3422         if (skinframe && skinframe->base)
3423                 return skinframe;
3424
3425         skinframe->stain = NULL;
3426         skinframe->merged = NULL;
3427         skinframe->base = NULL;
3428         skinframe->pants = NULL;
3429         skinframe->shirt = NULL;
3430         skinframe->nmap = NULL;
3431         skinframe->gloss = NULL;
3432         skinframe->glow = NULL;
3433         skinframe->fog = NULL;
3434         skinframe->reflect = NULL;
3435         skinframe->hasalpha = false;
3436
3437         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3438         if (!skindata)
3439                 return NULL;
3440
3441         if (developer_loading.integer)
3442                 Con_Printf("loading quake skin \"%s\"\n", name);
3443
3444         // 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)
3445         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3446         memcpy(skinframe->qpixels, skindata, width*height);
3447         skinframe->qwidth = width;
3448         skinframe->qheight = height;
3449
3450         featuresmask = 0;
3451         for (i = 0;i < width * height;i++)
3452                 featuresmask |= palette_featureflags[skindata[i]];
3453
3454         skinframe->hasalpha = false;
3455         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3456         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3457         skinframe->qgeneratemerged = true;
3458         skinframe->qgeneratebase = skinframe->qhascolormapping;
3459         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3460
3461         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3462         //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]);
3463
3464         return skinframe;
3465 }
3466
3467 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3468 {
3469         int width;
3470         int height;
3471         unsigned char *skindata;
3472
3473         if (!skinframe->qpixels)
3474                 return;
3475
3476         if (!skinframe->qhascolormapping)
3477                 colormapped = false;
3478
3479         if (colormapped)
3480         {
3481                 if (!skinframe->qgeneratebase)
3482                         return;
3483         }
3484         else
3485         {
3486                 if (!skinframe->qgeneratemerged)
3487                         return;
3488         }
3489
3490         width = skinframe->qwidth;
3491         height = skinframe->qheight;
3492         skindata = skinframe->qpixels;
3493
3494         if (skinframe->qgeneratenmap)
3495         {
3496                 unsigned char *temp1, *temp2;
3497                 skinframe->qgeneratenmap = false;
3498                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3499                 temp2 = temp1 + width * height * 4;
3500                 // use either a custom palette or the quake palette
3501                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3502                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3503                 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);
3504                 Mem_Free(temp1);
3505         }
3506
3507         if (skinframe->qgenerateglow)
3508         {
3509                 skinframe->qgenerateglow = false;
3510                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3511         }
3512
3513         if (colormapped)
3514         {
3515                 skinframe->qgeneratebase = false;
3516                 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);
3517                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3518                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3519         }
3520         else
3521         {
3522                 skinframe->qgeneratemerged = false;
3523                 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);
3524         }
3525
3526         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3527         {
3528                 Mem_Free(skinframe->qpixels);
3529                 skinframe->qpixels = NULL;
3530         }
3531 }
3532
3533 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)
3534 {
3535         int i;
3536         skinframe_t *skinframe;
3537
3538         if (cls.state == ca_dedicated)
3539                 return NULL;
3540
3541         // if already loaded just return it, otherwise make a new skinframe
3542         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3543         if (skinframe && skinframe->base)
3544                 return skinframe;
3545
3546         skinframe->stain = NULL;
3547         skinframe->merged = NULL;
3548         skinframe->base = NULL;
3549         skinframe->pants = NULL;
3550         skinframe->shirt = NULL;
3551         skinframe->nmap = NULL;
3552         skinframe->gloss = NULL;
3553         skinframe->glow = NULL;
3554         skinframe->fog = NULL;
3555         skinframe->reflect = NULL;
3556         skinframe->hasalpha = false;
3557
3558         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3559         if (!skindata)
3560                 return NULL;
3561
3562         if (developer_loading.integer)
3563                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3564
3565         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3566         if (textureflags & TEXF_ALPHA)
3567         {
3568                 for (i = 0;i < width * height;i++)
3569                 {
3570                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3571                         {
3572                                 skinframe->hasalpha = true;
3573                                 break;
3574                         }
3575                 }
3576                 if (r_loadfog && skinframe->hasalpha)
3577                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3578         }
3579
3580         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3581         //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]);
3582
3583         return skinframe;
3584 }
3585
3586 skinframe_t *R_SkinFrame_LoadMissing(void)
3587 {
3588         skinframe_t *skinframe;
3589
3590         if (cls.state == ca_dedicated)
3591                 return NULL;
3592
3593         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3594         skinframe->stain = NULL;
3595         skinframe->merged = NULL;
3596         skinframe->base = NULL;
3597         skinframe->pants = NULL;
3598         skinframe->shirt = NULL;
3599         skinframe->nmap = NULL;
3600         skinframe->gloss = NULL;
3601         skinframe->glow = NULL;
3602         skinframe->fog = NULL;
3603         skinframe->reflect = NULL;
3604         skinframe->hasalpha = false;
3605
3606         skinframe->avgcolor[0] = rand() / RAND_MAX;
3607         skinframe->avgcolor[1] = rand() / RAND_MAX;
3608         skinframe->avgcolor[2] = rand() / RAND_MAX;
3609         skinframe->avgcolor[3] = 1;
3610
3611         return skinframe;
3612 }
3613
3614 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3615 typedef struct suffixinfo_s
3616 {
3617         const char *suffix;
3618         qboolean flipx, flipy, flipdiagonal;
3619 }
3620 suffixinfo_t;
3621 static suffixinfo_t suffix[3][6] =
3622 {
3623         {
3624                 {"px",   false, false, false},
3625                 {"nx",   false, false, false},
3626                 {"py",   false, false, false},
3627                 {"ny",   false, false, false},
3628                 {"pz",   false, false, false},
3629                 {"nz",   false, false, false}
3630         },
3631         {
3632                 {"posx", false, false, false},
3633                 {"negx", false, false, false},
3634                 {"posy", false, false, false},
3635                 {"negy", false, false, false},
3636                 {"posz", false, false, false},
3637                 {"negz", false, false, false}
3638         },
3639         {
3640                 {"rt",    true, false,  true},
3641                 {"lf",   false,  true,  true},
3642                 {"ft",    true,  true, false},
3643                 {"bk",   false, false, false},
3644                 {"up",    true, false,  true},
3645                 {"dn",    true, false,  true}
3646         }
3647 };
3648
3649 static int componentorder[4] = {0, 1, 2, 3};
3650
3651 rtexture_t *R_LoadCubemap(const char *basename)
3652 {
3653         int i, j, cubemapsize;
3654         unsigned char *cubemappixels, *image_buffer;
3655         rtexture_t *cubemaptexture;
3656         char name[256];
3657         // must start 0 so the first loadimagepixels has no requested width/height
3658         cubemapsize = 0;
3659         cubemappixels = NULL;
3660         cubemaptexture = NULL;
3661         // keep trying different suffix groups (posx, px, rt) until one loads
3662         for (j = 0;j < 3 && !cubemappixels;j++)
3663         {
3664                 // load the 6 images in the suffix group
3665                 for (i = 0;i < 6;i++)
3666                 {
3667                         // generate an image name based on the base and and suffix
3668                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3669                         // load it
3670                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3671                         {
3672                                 // an image loaded, make sure width and height are equal
3673                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3674                                 {
3675                                         // if this is the first image to load successfully, allocate the cubemap memory
3676                                         if (!cubemappixels && image_width >= 1)
3677                                         {
3678                                                 cubemapsize = image_width;
3679                                                 // note this clears to black, so unavailable sides are black
3680                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3681                                         }
3682                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3683                                         if (cubemappixels)
3684                                                 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);
3685                                 }
3686                                 else
3687                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3688                                 // free the image
3689                                 Mem_Free(image_buffer);
3690                         }
3691                 }
3692         }
3693         // if a cubemap loaded, upload it
3694         if (cubemappixels)
3695         {
3696                 if (developer_loading.integer)
3697                         Con_Printf("loading cubemap \"%s\"\n", basename);
3698
3699                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3700                 Mem_Free(cubemappixels);
3701         }
3702         else
3703         {
3704                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3705                 if (developer_loading.integer)
3706                 {
3707                         Con_Printf("(tried tried images ");
3708                         for (j = 0;j < 3;j++)
3709                                 for (i = 0;i < 6;i++)
3710                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3711                         Con_Print(" and was unable to find any of them).\n");
3712                 }
3713         }
3714         return cubemaptexture;
3715 }
3716
3717 rtexture_t *R_GetCubemap(const char *basename)
3718 {
3719         int i;
3720         for (i = 0;i < r_texture_numcubemaps;i++)
3721                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3722                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3723         if (i >= MAX_CUBEMAPS)
3724                 return r_texture_whitecube;
3725         r_texture_numcubemaps++;
3726         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3727         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3728         return r_texture_cubemaps[i].texture;
3729 }
3730
3731 void R_FreeCubemaps(void)
3732 {
3733         int i;
3734         for (i = 0;i < r_texture_numcubemaps;i++)
3735         {
3736                 if (developer_loading.integer)
3737                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3738                 if (r_texture_cubemaps[i].texture)
3739                         R_FreeTexture(r_texture_cubemaps[i].texture);
3740         }
3741         r_texture_numcubemaps = 0;
3742 }
3743
3744 void R_Main_FreeViewCache(void)
3745 {
3746         if (r_refdef.viewcache.entityvisible)
3747                 Mem_Free(r_refdef.viewcache.entityvisible);
3748         if (r_refdef.viewcache.world_pvsbits)
3749                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3750         if (r_refdef.viewcache.world_leafvisible)
3751                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3752         if (r_refdef.viewcache.world_surfacevisible)
3753                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3754         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3755 }
3756
3757 void R_Main_ResizeViewCache(void)
3758 {
3759         int numentities = r_refdef.scene.numentities;
3760         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3761         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3762         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3763         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3764         if (r_refdef.viewcache.maxentities < numentities)
3765         {
3766                 r_refdef.viewcache.maxentities = numentities;
3767                 if (r_refdef.viewcache.entityvisible)
3768                         Mem_Free(r_refdef.viewcache.entityvisible);
3769                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3770         }
3771         if (r_refdef.viewcache.world_numclusters != numclusters)
3772         {
3773                 r_refdef.viewcache.world_numclusters = numclusters;
3774                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3775                 if (r_refdef.viewcache.world_pvsbits)
3776                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3777                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3778         }
3779         if (r_refdef.viewcache.world_numleafs != numleafs)
3780         {
3781                 r_refdef.viewcache.world_numleafs = numleafs;
3782                 if (r_refdef.viewcache.world_leafvisible)
3783                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3784                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3785         }
3786         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3787         {
3788                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3789                 if (r_refdef.viewcache.world_surfacevisible)
3790                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3791                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3792         }
3793 }
3794
3795 extern rtexture_t *loadingscreentexture;
3796 void gl_main_start(void)
3797 {
3798         loadingscreentexture = NULL;
3799         r_texture_blanknormalmap = NULL;
3800         r_texture_white = NULL;
3801         r_texture_grey128 = NULL;
3802         r_texture_black = NULL;
3803         r_texture_whitecube = NULL;
3804         r_texture_normalizationcube = NULL;
3805         r_texture_fogattenuation = NULL;
3806         r_texture_fogheighttexture = NULL;
3807         r_texture_gammaramps = NULL;
3808         r_texture_numcubemaps = 0;
3809
3810         r_loaddds = r_texture_dds_load.integer != 0;
3811         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3812
3813         switch(vid.renderpath)
3814         {
3815         case RENDERPATH_GL20:
3816         case RENDERPATH_D3D9:
3817         case RENDERPATH_D3D10:
3818         case RENDERPATH_D3D11:
3819         case RENDERPATH_SOFT:
3820                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3821                 Cvar_SetValueQuick(&gl_combine, 1);
3822                 Cvar_SetValueQuick(&r_glsl, 1);
3823                 r_loadnormalmap = true;
3824                 r_loadgloss = true;
3825                 r_loadfog = false;
3826                 break;
3827         case RENDERPATH_GL13:
3828                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3829                 Cvar_SetValueQuick(&gl_combine, 1);
3830                 Cvar_SetValueQuick(&r_glsl, 0);
3831                 r_loadnormalmap = false;
3832                 r_loadgloss = false;
3833                 r_loadfog = true;
3834                 break;
3835         case RENDERPATH_GL11:
3836                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3837                 Cvar_SetValueQuick(&gl_combine, 0);
3838                 Cvar_SetValueQuick(&r_glsl, 0);
3839                 r_loadnormalmap = false;
3840                 r_loadgloss = false;
3841                 r_loadfog = true;
3842                 break;
3843         case RENDERPATH_GLES2:
3844                 Cvar_SetValueQuick(&r_textureunits, 1);
3845                 Cvar_SetValueQuick(&gl_combine, 1);
3846                 Cvar_SetValueQuick(&r_glsl, 1);
3847                 r_loadnormalmap = true;
3848                 r_loadgloss = false;
3849                 r_loadfog = false;
3850                 break;
3851         }
3852
3853         R_AnimCache_Free();
3854         R_FrameData_Reset();
3855
3856         r_numqueries = 0;
3857         r_maxqueries = 0;
3858         memset(r_queries, 0, sizeof(r_queries));
3859
3860         r_qwskincache = NULL;
3861         r_qwskincache_size = 0;
3862
3863         // due to caching of texture_t references, the collision cache must be reset
3864         Collision_Cache_Reset(true);
3865
3866         // set up r_skinframe loading system for textures
3867         memset(&r_skinframe, 0, sizeof(r_skinframe));
3868         r_skinframe.loadsequence = 1;
3869         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3870
3871         r_main_texturepool = R_AllocTexturePool();
3872         R_BuildBlankTextures();
3873         R_BuildNoTexture();
3874         if (vid.support.arb_texture_cube_map)
3875         {
3876                 R_BuildWhiteCube();
3877                 R_BuildNormalizationCube();
3878         }
3879         r_texture_fogattenuation = NULL;
3880         r_texture_fogheighttexture = NULL;
3881         r_texture_gammaramps = NULL;
3882         //r_texture_fogintensity = NULL;
3883         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3884         memset(&r_waterstate, 0, sizeof(r_waterstate));
3885         r_glsl_permutation = NULL;
3886         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3887         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3888         glslshaderstring = NULL;
3889 #ifdef SUPPORTD3D
3890         r_hlsl_permutation = NULL;
3891         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3892         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3893 #endif
3894         hlslshaderstring = NULL;
3895         memset(&r_svbsp, 0, sizeof (r_svbsp));
3896
3897         r_refdef.fogmasktable_density = 0;
3898 }
3899
3900 void gl_main_shutdown(void)
3901 {
3902         R_AnimCache_Free();
3903         R_FrameData_Reset();
3904
3905         R_Main_FreeViewCache();
3906
3907         switch(vid.renderpath)
3908         {
3909         case RENDERPATH_GL11:
3910         case RENDERPATH_GL13:
3911         case RENDERPATH_GL20:
3912         case RENDERPATH_GLES2:
3913                 if (r_maxqueries)
3914                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3915                 break;
3916         case RENDERPATH_D3D9:
3917                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3918                 break;
3919         case RENDERPATH_D3D10:
3920                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3921                 break;
3922         case RENDERPATH_D3D11:
3923                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3924                 break;
3925         case RENDERPATH_SOFT:
3926                 break;
3927         }
3928
3929         r_numqueries = 0;
3930         r_maxqueries = 0;
3931         memset(r_queries, 0, sizeof(r_queries));
3932
3933         r_qwskincache = NULL;
3934         r_qwskincache_size = 0;
3935
3936         // clear out the r_skinframe state
3937         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3938         memset(&r_skinframe, 0, sizeof(r_skinframe));
3939
3940         if (r_svbsp.nodes)
3941                 Mem_Free(r_svbsp.nodes);
3942         memset(&r_svbsp, 0, sizeof (r_svbsp));
3943         R_FreeTexturePool(&r_main_texturepool);
3944         loadingscreentexture = NULL;
3945         r_texture_blanknormalmap = NULL;
3946         r_texture_white = NULL;
3947         r_texture_grey128 = NULL;
3948         r_texture_black = NULL;
3949         r_texture_whitecube = NULL;
3950         r_texture_normalizationcube = NULL;
3951         r_texture_fogattenuation = NULL;
3952         r_texture_fogheighttexture = NULL;
3953         r_texture_gammaramps = NULL;
3954         r_texture_numcubemaps = 0;
3955         //r_texture_fogintensity = NULL;
3956         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3957         memset(&r_waterstate, 0, sizeof(r_waterstate));
3958         R_GLSL_Restart_f();
3959
3960         r_glsl_permutation = NULL;
3961         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3962         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3963         glslshaderstring = NULL;
3964 #ifdef SUPPORTD3D
3965         r_hlsl_permutation = NULL;
3966         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3967         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3968 #endif
3969         hlslshaderstring = NULL;
3970 }
3971
3972 extern void CL_ParseEntityLump(char *entitystring);
3973 void gl_main_newmap(void)
3974 {
3975         // FIXME: move this code to client
3976         char *entities, entname[MAX_QPATH];
3977         if (r_qwskincache)
3978                 Mem_Free(r_qwskincache);
3979         r_qwskincache = NULL;
3980         r_qwskincache_size = 0;
3981         if (cl.worldmodel)
3982         {
3983                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3984                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3985                 {
3986                         CL_ParseEntityLump(entities);
3987                         Mem_Free(entities);
3988                         return;
3989                 }
3990                 if (cl.worldmodel->brush.entities)
3991                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3992         }
3993         R_Main_FreeViewCache();
3994
3995         R_FrameData_Reset();
3996 }
3997
3998 void GL_Main_Init(void)
3999 {
4000         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4001
4002         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4003         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4004         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4005         if (gamemode == GAME_NEHAHRA)
4006         {
4007                 Cvar_RegisterVariable (&gl_fogenable);
4008                 Cvar_RegisterVariable (&gl_fogdensity);
4009                 Cvar_RegisterVariable (&gl_fogred);
4010                 Cvar_RegisterVariable (&gl_foggreen);
4011                 Cvar_RegisterVariable (&gl_fogblue);
4012                 Cvar_RegisterVariable (&gl_fogstart);
4013                 Cvar_RegisterVariable (&gl_fogend);
4014                 Cvar_RegisterVariable (&gl_skyclip);
4015         }
4016         Cvar_RegisterVariable(&r_motionblur);
4017         Cvar_RegisterVariable(&r_motionblur_maxblur);
4018         Cvar_RegisterVariable(&r_motionblur_bmin);
4019         Cvar_RegisterVariable(&r_motionblur_vmin);
4020         Cvar_RegisterVariable(&r_motionblur_vmax);
4021         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4022         Cvar_RegisterVariable(&r_motionblur_randomize);
4023         Cvar_RegisterVariable(&r_damageblur);
4024         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4025         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4026         Cvar_RegisterVariable(&r_equalize_entities_by);
4027         Cvar_RegisterVariable(&r_equalize_entities_to);
4028         Cvar_RegisterVariable(&r_depthfirst);
4029         Cvar_RegisterVariable(&r_useinfinitefarclip);
4030         Cvar_RegisterVariable(&r_farclip_base);
4031         Cvar_RegisterVariable(&r_farclip_world);
4032         Cvar_RegisterVariable(&r_nearclip);
4033         Cvar_RegisterVariable(&r_showbboxes);
4034         Cvar_RegisterVariable(&r_showsurfaces);
4035         Cvar_RegisterVariable(&r_showtris);
4036         Cvar_RegisterVariable(&r_shownormals);
4037         Cvar_RegisterVariable(&r_showlighting);
4038         Cvar_RegisterVariable(&r_showshadowvolumes);
4039         Cvar_RegisterVariable(&r_showcollisionbrushes);
4040         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4041         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4042         Cvar_RegisterVariable(&r_showdisabledepthtest);
4043         Cvar_RegisterVariable(&r_drawportals);
4044         Cvar_RegisterVariable(&r_drawentities);
4045         Cvar_RegisterVariable(&r_draw2d);
4046         Cvar_RegisterVariable(&r_drawworld);
4047         Cvar_RegisterVariable(&r_cullentities_trace);
4048         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4049         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4050         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4051         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4052         Cvar_RegisterVariable(&r_drawviewmodel);
4053         Cvar_RegisterVariable(&r_drawexteriormodel);
4054         Cvar_RegisterVariable(&r_speeds);
4055         Cvar_RegisterVariable(&r_fullbrights);
4056         Cvar_RegisterVariable(&r_wateralpha);
4057         Cvar_RegisterVariable(&r_dynamic);
4058         Cvar_RegisterVariable(&r_fakelight);
4059         Cvar_RegisterVariable(&r_fakelight_intensity);
4060         Cvar_RegisterVariable(&r_fullbright);
4061         Cvar_RegisterVariable(&r_shadows);
4062         Cvar_RegisterVariable(&r_shadows_darken);
4063         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4064         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4065         Cvar_RegisterVariable(&r_shadows_throwdistance);
4066         Cvar_RegisterVariable(&r_shadows_throwdirection);
4067         Cvar_RegisterVariable(&r_shadows_focus);
4068         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4069         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4070         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4071         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4072         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4073         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4074         Cvar_RegisterVariable(&r_fog_exp2);
4075         Cvar_RegisterVariable(&r_drawfog);
4076         Cvar_RegisterVariable(&r_transparentdepthmasking);
4077         Cvar_RegisterVariable(&r_texture_dds_load);
4078         Cvar_RegisterVariable(&r_texture_dds_save);
4079         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4080         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4081         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4082         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4083         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4084         Cvar_RegisterVariable(&r_textureunits);
4085         Cvar_RegisterVariable(&gl_combine);
4086         Cvar_RegisterVariable(&r_glsl);
4087         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4088         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4089         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4090         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4091         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4092         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4093         Cvar_RegisterVariable(&r_glsl_postprocess);
4094         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4095         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4096         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4097         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4098         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4099         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4100         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4101         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4102
4103         Cvar_RegisterVariable(&r_water);
4104         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4105         Cvar_RegisterVariable(&r_water_clippingplanebias);
4106         Cvar_RegisterVariable(&r_water_refractdistort);
4107         Cvar_RegisterVariable(&r_water_reflectdistort);
4108         Cvar_RegisterVariable(&r_water_scissormode);
4109         Cvar_RegisterVariable(&r_lerpsprites);
4110         Cvar_RegisterVariable(&r_lerpmodels);
4111         Cvar_RegisterVariable(&r_lerplightstyles);
4112         Cvar_RegisterVariable(&r_waterscroll);
4113         Cvar_RegisterVariable(&r_bloom);
4114         Cvar_RegisterVariable(&r_bloom_colorscale);
4115         Cvar_RegisterVariable(&r_bloom_brighten);
4116         Cvar_RegisterVariable(&r_bloom_blur);
4117         Cvar_RegisterVariable(&r_bloom_resolution);
4118         Cvar_RegisterVariable(&r_bloom_colorexponent);
4119         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4120         Cvar_RegisterVariable(&r_hdr);
4121         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4122         Cvar_RegisterVariable(&r_hdr_glowintensity);
4123         Cvar_RegisterVariable(&r_hdr_range);
4124         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4125         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4126         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4127         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4128         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4129         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4130         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4131         Cvar_RegisterVariable(&developer_texturelogging);
4132         Cvar_RegisterVariable(&gl_lightmaps);
4133         Cvar_RegisterVariable(&r_test);
4134         Cvar_RegisterVariable(&r_glsl_saturation);
4135         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4136         Cvar_RegisterVariable(&r_framedatasize);
4137         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4138                 Cvar_SetValue("r_fullbrights", 0);
4139         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4140
4141         Cvar_RegisterVariable(&r_track_sprites);
4142         Cvar_RegisterVariable(&r_track_sprites_flags);
4143         Cvar_RegisterVariable(&r_track_sprites_scalew);
4144         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4145         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4146         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4147         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4148         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4149 }
4150
4151 extern void R_Textures_Init(void);
4152 extern void GL_Draw_Init(void);
4153 extern void GL_Main_Init(void);
4154 extern void R_Shadow_Init(void);
4155 extern void R_Sky_Init(void);
4156 extern void GL_Surf_Init(void);
4157 extern void R_Particles_Init(void);
4158 extern void R_Explosion_Init(void);
4159 extern void gl_backend_init(void);
4160 extern void Sbar_Init(void);
4161 extern void R_LightningBeams_Init(void);
4162 extern void Mod_RenderInit(void);
4163 extern void Font_Init(void);
4164
4165 void Render_Init(void)
4166 {
4167         gl_backend_init();
4168         R_Textures_Init();
4169         GL_Main_Init();
4170         Font_Init();
4171         GL_Draw_Init();
4172         R_Shadow_Init();
4173         R_Sky_Init();
4174         GL_Surf_Init();
4175         Sbar_Init();
4176         R_Particles_Init();
4177         R_Explosion_Init();
4178         R_LightningBeams_Init();
4179         Mod_RenderInit();
4180 }
4181
4182 /*
4183 ===============
4184 GL_Init
4185 ===============
4186 */
4187 extern char *ENGINE_EXTENSIONS;
4188 void GL_Init (void)
4189 {
4190         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4191         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4192         gl_version = (const char *)qglGetString(GL_VERSION);
4193         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4194
4195         if (!gl_extensions)
4196                 gl_extensions = "";
4197         if (!gl_platformextensions)
4198                 gl_platformextensions = "";
4199
4200         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4201         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4202         Con_Printf("GL_VERSION: %s\n", gl_version);
4203         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4204         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4205
4206         VID_CheckExtensions();
4207
4208         // LordHavoc: report supported extensions
4209         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4210
4211         // clear to black (loading plaque will be seen over this)
4212         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4213 }
4214
4215 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4216 {
4217         int i;
4218         mplane_t *p;
4219         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4220         {
4221                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4222                 if (i == 4)
4223                         continue;
4224                 p = r_refdef.view.frustum + i;
4225                 switch(p->signbits)
4226                 {
4227                 default:
4228                 case 0:
4229                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4230                                 return true;
4231                         break;
4232                 case 1:
4233                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4234                                 return true;
4235                         break;
4236                 case 2:
4237                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4238                                 return true;
4239                         break;
4240                 case 3:
4241                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4242                                 return true;
4243                         break;
4244                 case 4:
4245                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4246                                 return true;
4247                         break;
4248                 case 5:
4249                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4250                                 return true;
4251                         break;
4252                 case 6:
4253                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4254                                 return true;
4255                         break;
4256                 case 7:
4257                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4258                                 return true;
4259                         break;
4260                 }
4261         }
4262         return false;
4263 }
4264
4265 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4266 {
4267         int i;
4268         const mplane_t *p;
4269         for (i = 0;i < numplanes;i++)
4270         {
4271                 p = planes + i;
4272                 switch(p->signbits)
4273                 {
4274                 default:
4275                 case 0:
4276                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4277                                 return true;
4278                         break;
4279                 case 1:
4280                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4281                                 return true;
4282                         break;
4283                 case 2:
4284                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 case 3:
4288                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 4:
4292                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 case 5:
4296                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4297                                 return true;
4298                         break;
4299                 case 6:
4300                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4301                                 return true;
4302                         break;
4303                 case 7:
4304                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4305                                 return true;
4306                         break;
4307                 }
4308         }
4309         return false;
4310 }
4311
4312 //==================================================================================
4313
4314 // LordHavoc: this stores temporary data used within the same frame
4315
4316 typedef struct r_framedata_mem_s
4317 {
4318         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4319         size_t size; // how much usable space
4320         size_t current; // how much space in use
4321         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4322         size_t wantedsize; // how much space was allocated
4323         unsigned char *data; // start of real data (16byte aligned)
4324 }
4325 r_framedata_mem_t;
4326
4327 static r_framedata_mem_t *r_framedata_mem;
4328
4329 void R_FrameData_Reset(void)
4330 {
4331         while (r_framedata_mem)
4332         {
4333                 r_framedata_mem_t *next = r_framedata_mem->purge;
4334                 Mem_Free(r_framedata_mem);
4335                 r_framedata_mem = next;
4336         }
4337 }
4338
4339 void R_FrameData_Resize(void)
4340 {
4341         size_t wantedsize;
4342         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4343         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4344         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4345         {
4346                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4347                 newmem->wantedsize = wantedsize;
4348                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4349                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4350                 newmem->current = 0;
4351                 newmem->mark = 0;
4352                 newmem->purge = r_framedata_mem;
4353                 r_framedata_mem = newmem;
4354         }
4355 }
4356
4357 void R_FrameData_NewFrame(void)
4358 {
4359         R_FrameData_Resize();
4360         if (!r_framedata_mem)
4361                 return;
4362         // if we ran out of space on the last frame, free the old memory now
4363         while (r_framedata_mem->purge)
4364         {
4365                 // repeatedly remove the second item in the list, leaving only head
4366                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4367                 Mem_Free(r_framedata_mem->purge);
4368                 r_framedata_mem->purge = next;
4369         }
4370         // reset the current mem pointer
4371         r_framedata_mem->current = 0;
4372         r_framedata_mem->mark = 0;
4373 }
4374
4375 void *R_FrameData_Alloc(size_t size)
4376 {
4377         void *data;
4378
4379         // align to 16 byte boundary - the data pointer is already aligned, so we
4380         // only need to ensure the size of every allocation is also aligned
4381         size = (size + 15) & ~15;
4382
4383         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4384         {
4385                 // emergency - we ran out of space, allocate more memory
4386                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4387                 R_FrameData_Resize();
4388         }
4389
4390         data = r_framedata_mem->data + r_framedata_mem->current;
4391         r_framedata_mem->current += size;
4392
4393         // count the usage for stats
4394         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4395         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4396
4397         return (void *)data;
4398 }
4399
4400 void *R_FrameData_Store(size_t size, void *data)
4401 {
4402         void *d = R_FrameData_Alloc(size);
4403         if (d && data)
4404                 memcpy(d, data, size);
4405         return d;
4406 }
4407
4408 void R_FrameData_SetMark(void)
4409 {
4410         if (!r_framedata_mem)
4411                 return;
4412         r_framedata_mem->mark = r_framedata_mem->current;
4413 }
4414
4415 void R_FrameData_ReturnToMark(void)
4416 {
4417         if (!r_framedata_mem)
4418                 return;
4419         r_framedata_mem->current = r_framedata_mem->mark;
4420 }
4421
4422 //==================================================================================
4423
4424 // LordHavoc: animcache originally written by Echon, rewritten since then
4425
4426 /**
4427  * Animation cache prevents re-generating mesh data for an animated model
4428  * multiple times in one frame for lighting, shadowing, reflections, etc.
4429  */
4430
4431 void R_AnimCache_Free(void)
4432 {
4433 }
4434
4435 void R_AnimCache_ClearCache(void)
4436 {
4437         int i;
4438         entity_render_t *ent;
4439
4440         for (i = 0;i < r_refdef.scene.numentities;i++)
4441         {
4442                 ent = r_refdef.scene.entities[i];
4443                 ent->animcache_vertex3f = NULL;
4444                 ent->animcache_normal3f = NULL;
4445                 ent->animcache_svector3f = NULL;
4446                 ent->animcache_tvector3f = NULL;
4447                 ent->animcache_vertexmesh = NULL;
4448                 ent->animcache_vertex3fbuffer = NULL;
4449                 ent->animcache_vertexmeshbuffer = NULL;
4450         }
4451 }
4452
4453 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4454 {
4455         int i;
4456
4457         // check if we need the meshbuffers
4458         if (!vid.useinterleavedarrays)
4459                 return;
4460
4461         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4462                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4463         // TODO: upload vertex3f buffer?
4464         if (ent->animcache_vertexmesh)
4465         {
4466                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4467                 for (i = 0;i < numvertices;i++)
4468                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4469                 if (ent->animcache_svector3f)
4470                         for (i = 0;i < numvertices;i++)
4471                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4472                 if (ent->animcache_tvector3f)
4473                         for (i = 0;i < numvertices;i++)
4474                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4475                 if (ent->animcache_normal3f)
4476                         for (i = 0;i < numvertices;i++)
4477                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4478                 // TODO: upload vertexmeshbuffer?
4479         }
4480 }
4481
4482 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4483 {
4484         dp_model_t *model = ent->model;
4485         int numvertices;
4486         // see if it's already cached this frame
4487         if (ent->animcache_vertex3f)
4488         {
4489                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4490                 if (wantnormals || wanttangents)
4491                 {
4492                         if (ent->animcache_normal3f)
4493                                 wantnormals = false;
4494                         if (ent->animcache_svector3f)
4495                                 wanttangents = false;
4496                         if (wantnormals || wanttangents)
4497                         {
4498                                 numvertices = model->surfmesh.num_vertices;
4499                                 if (wantnormals)
4500                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4501                                 if (wanttangents)
4502                                 {
4503                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4504                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4505                                 }
4506                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4507                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4508                         }
4509                 }
4510         }
4511         else
4512         {
4513                 // see if this ent is worth caching
4514                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4515                         return false;
4516                 // get some memory for this entity and generate mesh data
4517                 numvertices = model->surfmesh.num_vertices;
4518                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4519                 if (wantnormals)
4520                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4521                 if (wanttangents)
4522                 {
4523                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4524                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4525                 }
4526                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4527                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4528         }
4529         return true;
4530 }
4531
4532 void R_AnimCache_CacheVisibleEntities(void)
4533 {
4534         int i;
4535         qboolean wantnormals = true;
4536         qboolean wanttangents = !r_showsurfaces.integer;
4537
4538         switch(vid.renderpath)
4539         {
4540         case RENDERPATH_GL20:
4541         case RENDERPATH_D3D9:
4542         case RENDERPATH_D3D10:
4543         case RENDERPATH_D3D11:
4544         case RENDERPATH_GLES2:
4545                 break;
4546         case RENDERPATH_GL13:
4547         case RENDERPATH_GL11:
4548                 wanttangents = false;
4549                 break;
4550         case RENDERPATH_SOFT:
4551                 break;
4552         }
4553
4554         if (r_shownormals.integer)
4555                 wanttangents = wantnormals = true;
4556
4557         // TODO: thread this
4558         // NOTE: R_PrepareRTLights() also caches entities
4559
4560         for (i = 0;i < r_refdef.scene.numentities;i++)
4561                 if (r_refdef.viewcache.entityvisible[i])
4562                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4563 }
4564
4565 //==================================================================================
4566
4567 static void R_View_UpdateEntityLighting (void)
4568 {
4569         int i;
4570         entity_render_t *ent;
4571         vec3_t tempdiffusenormal, avg;
4572         vec_t f, fa, fd, fdd;
4573         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4574
4575         for (i = 0;i < r_refdef.scene.numentities;i++)
4576         {
4577                 ent = r_refdef.scene.entities[i];
4578
4579                 // skip unseen models
4580                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4581                         continue;
4582
4583                 // skip bsp models
4584                 if (ent->model && ent->model->brush.num_leafs)
4585                 {
4586                         // TODO: use modellight for r_ambient settings on world?
4587                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4588                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4589                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4590                         continue;
4591                 }
4592
4593                 // fetch the lighting from the worldmodel data
4594                 VectorClear(ent->modellight_ambient);
4595                 VectorClear(ent->modellight_diffuse);
4596                 VectorClear(tempdiffusenormal);
4597                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4598                 {
4599                         vec3_t org;
4600                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4601
4602                         // complete lightning for lit sprites
4603                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4604                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4605                         {
4606                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4607                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4608                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4609                         }
4610                         else
4611                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4612
4613                         if(ent->flags & RENDER_EQUALIZE)
4614                         {
4615                                 // first fix up ambient lighting...
4616                                 if(r_equalize_entities_minambient.value > 0)
4617                                 {
4618                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4619                                         if(fd > 0)
4620                                         {
4621                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4622                                                 if(fa < r_equalize_entities_minambient.value * fd)
4623                                                 {
4624                                                         // solve:
4625                                                         //   fa'/fd' = minambient
4626                                                         //   fa'+0.25*fd' = fa+0.25*fd
4627                                                         //   ...
4628                                                         //   fa' = fd' * minambient
4629                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4630                                                         //   ...
4631                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4632                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4633                                                         //   ...
4634                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4635                                                         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
4636                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4637                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4638                                                 }
4639                                         }
4640                                 }
4641
4642                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4643                                 {
4644                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4645                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4646                                         f = fa + 0.25 * fd;
4647                                         if(f > 0)
4648                                         {
4649                                                 // adjust brightness and saturation to target
4650                                                 avg[0] = avg[1] = avg[2] = fa / f;
4651                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4652                                                 avg[0] = avg[1] = avg[2] = fd / f;
4653                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4654                                         }
4655                                 }
4656                         }
4657                 }
4658                 else // highly rare
4659                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4660
4661                 // move the light direction into modelspace coordinates for lighting code
4662                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4663                 if(VectorLength2(ent->modellight_lightdir) == 0)
4664                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4665                 VectorNormalize(ent->modellight_lightdir);
4666         }
4667 }
4668
4669 #define MAX_LINEOFSIGHTTRACES 64
4670
4671 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4672 {
4673         int i;
4674         vec3_t boxmins, boxmaxs;
4675         vec3_t start;
4676         vec3_t end;
4677         dp_model_t *model = r_refdef.scene.worldmodel;
4678
4679         if (!model || !model->brush.TraceLineOfSight)
4680                 return true;
4681
4682         // expand the box a little
4683         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4684         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4685         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4686         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4687         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4688         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4689
4690         // return true if eye is inside enlarged box
4691         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4692                 return true;
4693
4694         // try center
4695         VectorCopy(eye, start);
4696         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4697         if (model->brush.TraceLineOfSight(model, start, end))
4698                 return true;
4699
4700         // try various random positions
4701         for (i = 0;i < numsamples;i++)
4702         {
4703                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4704                 if (model->brush.TraceLineOfSight(model, start, end))
4705                         return true;
4706         }
4707
4708         return false;
4709 }
4710
4711
4712 static void R_View_UpdateEntityVisible (void)
4713 {
4714         int i;
4715         int renderimask;
4716         int samples;
4717         entity_render_t *ent;
4718
4719         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4720                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4721                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4722                 :                                                          RENDER_EXTERIORMODEL;
4723         if (!r_drawviewmodel.integer)
4724                 renderimask |= RENDER_VIEWMODEL;
4725         if (!r_drawexteriormodel.integer)
4726                 renderimask |= RENDER_EXTERIORMODEL;
4727         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4728         {
4729                 // worldmodel can check visibility
4730                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4731                 for (i = 0;i < r_refdef.scene.numentities;i++)
4732                 {
4733                         ent = r_refdef.scene.entities[i];
4734                         if (!(ent->flags & renderimask))
4735                         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)))
4736                         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))
4737                                 r_refdef.viewcache.entityvisible[i] = true;
4738                 }
4739                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4740                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4741                 {
4742                         for (i = 0;i < r_refdef.scene.numentities;i++)
4743                         {
4744                                 ent = r_refdef.scene.entities[i];
4745                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4746                                 {
4747                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4748                                         if (samples < 0)
4749                                                 continue; // temp entities do pvs only
4750                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4751                                                 ent->last_trace_visibility = realtime;
4752                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4753                                                 r_refdef.viewcache.entityvisible[i] = 0;
4754                                 }
4755                         }
4756                 }
4757         }
4758         else
4759         {
4760                 // no worldmodel or it can't check visibility
4761                 for (i = 0;i < r_refdef.scene.numentities;i++)
4762                 {
4763                         ent = r_refdef.scene.entities[i];
4764                         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));
4765                 }
4766         }
4767 }
4768
4769 /// only used if skyrendermasked, and normally returns false
4770 int R_DrawBrushModelsSky (void)
4771 {
4772         int i, sky;
4773         entity_render_t *ent;
4774
4775         sky = false;
4776         for (i = 0;i < r_refdef.scene.numentities;i++)
4777         {
4778                 if (!r_refdef.viewcache.entityvisible[i])
4779                         continue;
4780                 ent = r_refdef.scene.entities[i];
4781                 if (!ent->model || !ent->model->DrawSky)
4782                         continue;
4783                 ent->model->DrawSky(ent);
4784                 sky = true;
4785         }
4786         return sky;
4787 }
4788
4789 static void R_DrawNoModel(entity_render_t *ent);
4790 static void R_DrawModels(void)
4791 {
4792         int i;
4793         entity_render_t *ent;
4794
4795         for (i = 0;i < r_refdef.scene.numentities;i++)
4796         {
4797                 if (!r_refdef.viewcache.entityvisible[i])
4798                         continue;
4799                 ent = r_refdef.scene.entities[i];
4800                 r_refdef.stats.entities++;
4801                 if (ent->model && ent->model->Draw != NULL)
4802                         ent->model->Draw(ent);
4803                 else
4804                         R_DrawNoModel(ent);
4805         }
4806 }
4807
4808 static void R_DrawModelsDepth(void)
4809 {
4810         int i;
4811         entity_render_t *ent;
4812
4813         for (i = 0;i < r_refdef.scene.numentities;i++)
4814         {
4815                 if (!r_refdef.viewcache.entityvisible[i])
4816                         continue;
4817                 ent = r_refdef.scene.entities[i];
4818                 if (ent->model && ent->model->DrawDepth != NULL)
4819                         ent->model->DrawDepth(ent);
4820         }
4821 }
4822
4823 static void R_DrawModelsDebug(void)
4824 {
4825         int i;
4826         entity_render_t *ent;
4827
4828         for (i = 0;i < r_refdef.scene.numentities;i++)
4829         {
4830                 if (!r_refdef.viewcache.entityvisible[i])
4831                         continue;
4832                 ent = r_refdef.scene.entities[i];
4833                 if (ent->model && ent->model->DrawDebug != NULL)
4834                         ent->model->DrawDebug(ent);
4835         }
4836 }
4837
4838 static void R_DrawModelsAddWaterPlanes(void)
4839 {
4840         int i;
4841         entity_render_t *ent;
4842
4843         for (i = 0;i < r_refdef.scene.numentities;i++)
4844         {
4845                 if (!r_refdef.viewcache.entityvisible[i])
4846                         continue;
4847                 ent = r_refdef.scene.entities[i];
4848                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4849                         ent->model->DrawAddWaterPlanes(ent);
4850         }
4851 }
4852
4853 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4854 {
4855         if (r_hdr_irisadaptation.integer)
4856         {
4857                 vec3_t ambient;
4858                 vec3_t diffuse;
4859                 vec3_t diffusenormal;
4860                 vec_t brightness;
4861                 vec_t goal;
4862                 vec_t adjust;
4863                 vec_t current;
4864                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4865                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4866                 brightness = max(0.0000001f, brightness);
4867                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4868                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4869                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4870                 current = r_hdr_irisadaptation_value.value;
4871                 if (current < goal)
4872                         current = min(current + adjust, goal);
4873                 else if (current > goal)
4874                         current = max(current - adjust, goal);
4875                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4876                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4877         }
4878         else if (r_hdr_irisadaptation_value.value != 1.0f)
4879                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4880 }
4881
4882 static void R_View_SetFrustum(const int *scissor)
4883 {
4884         int i;
4885         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4886         vec3_t forward, left, up, origin, v;
4887
4888         if(scissor)
4889         {
4890                 // flipped x coordinates (because x points left here)
4891                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4892                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4893
4894                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4895                 switch(vid.renderpath)
4896                 {
4897                         case RENDERPATH_D3D9:
4898                         case RENDERPATH_D3D10:
4899                         case RENDERPATH_D3D11:
4900                         case RENDERPATH_SOFT:
4901                                 // non-flipped y coordinates
4902                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4903                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4904                                 break;
4905                         case RENDERPATH_GL11:
4906                         case RENDERPATH_GL13:
4907                         case RENDERPATH_GL20:
4908                         case RENDERPATH_GLES2:
4909                                 // non-flipped y coordinates
4910                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4911                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4912                                 break;
4913                 }
4914         }
4915
4916         // we can't trust r_refdef.view.forward and friends in reflected scenes
4917         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4918
4919 #if 0
4920         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4921         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4922         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4923         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4924         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4925         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4926         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4927         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4928         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4929         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4930         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4931         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4932 #endif
4933
4934 #if 0
4935         zNear = r_refdef.nearclip;
4936         nudge = 1.0 - 1.0 / (1<<23);
4937         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4938         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4939         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4940         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4941         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4942         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4943         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4944         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4945 #endif
4946
4947
4948
4949 #if 0
4950         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4951         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4952         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4953         r_refdef.view.frustum[0].dist = m[15] - m[12];
4954
4955         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4956         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4957         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4958         r_refdef.view.frustum[1].dist = m[15] + m[12];
4959
4960         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4961         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4962         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4963         r_refdef.view.frustum[2].dist = m[15] - m[13];
4964
4965         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4966         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4967         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4968         r_refdef.view.frustum[3].dist = m[15] + m[13];
4969
4970         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4971         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4972         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4973         r_refdef.view.frustum[4].dist = m[15] - m[14];
4974
4975         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4976         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4977         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4978         r_refdef.view.frustum[5].dist = m[15] + m[14];
4979 #endif
4980
4981         if (r_refdef.view.useperspective)
4982         {
4983                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4984                 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]);
4985                 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]);
4986                 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]);
4987                 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]);
4988
4989                 // then the normals from the corners relative to origin
4990                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4991                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4992                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4993                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4994
4995                 // in a NORMAL view, forward cross left == up
4996                 // in a REFLECTED view, forward cross left == down
4997                 // so our cross products above need to be adjusted for a left handed coordinate system
4998                 CrossProduct(forward, left, v);
4999                 if(DotProduct(v, up) < 0)
5000                 {
5001                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5002                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5003                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5004                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5005                 }
5006
5007                 // Leaving those out was a mistake, those were in the old code, and they
5008                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5009                 // I couldn't reproduce it after adding those normalizations. --blub
5010                 VectorNormalize(r_refdef.view.frustum[0].normal);
5011                 VectorNormalize(r_refdef.view.frustum[1].normal);
5012                 VectorNormalize(r_refdef.view.frustum[2].normal);
5013                 VectorNormalize(r_refdef.view.frustum[3].normal);
5014
5015                 // make the corners absolute
5016                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5017                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5018                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5019                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5020
5021                 // one more normal
5022                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5023
5024                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5025                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5026                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5027                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5028                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5029         }
5030         else
5031         {
5032                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5033                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5034                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5035                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5036                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5037                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5038                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5039                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5040                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5041                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5042         }
5043         r_refdef.view.numfrustumplanes = 5;
5044
5045         if (r_refdef.view.useclipplane)
5046         {
5047                 r_refdef.view.numfrustumplanes = 6;
5048                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5049         }
5050
5051         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5052                 PlaneClassify(r_refdef.view.frustum + i);
5053
5054         // LordHavoc: note to all quake engine coders, Quake had a special case
5055         // for 90 degrees which assumed a square view (wrong), so I removed it,
5056         // Quake2 has it disabled as well.
5057
5058         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5059         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5060         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5061         //PlaneClassify(&frustum[0]);
5062
5063         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5064         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5065         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5066         //PlaneClassify(&frustum[1]);
5067
5068         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5069         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5070         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5071         //PlaneClassify(&frustum[2]);
5072
5073         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5074         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5075         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5076         //PlaneClassify(&frustum[3]);
5077
5078         // nearclip plane
5079         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5080         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5081         //PlaneClassify(&frustum[4]);
5082 }
5083
5084 void R_View_UpdateWithScissor(const int *myscissor)
5085 {
5086         R_Main_ResizeViewCache();
5087         R_View_SetFrustum(myscissor);
5088         R_View_WorldVisibility(r_refdef.view.useclipplane);
5089         R_View_UpdateEntityVisible();
5090         R_View_UpdateEntityLighting();
5091 }
5092
5093 void R_View_Update(void)
5094 {
5095         R_Main_ResizeViewCache();
5096         R_View_SetFrustum(NULL);
5097         R_View_WorldVisibility(r_refdef.view.useclipplane);
5098         R_View_UpdateEntityVisible();
5099         R_View_UpdateEntityLighting();
5100 }
5101
5102 void R_SetupView(qboolean allowwaterclippingplane)
5103 {
5104         const float *customclipplane = NULL;
5105         float plane[4];
5106         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5107         {
5108                 // LordHavoc: couldn't figure out how to make this approach the
5109                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5110                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5111                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5112                         dist = r_refdef.view.clipplane.dist;
5113                 plane[0] = r_refdef.view.clipplane.normal[0];
5114                 plane[1] = r_refdef.view.clipplane.normal[1];
5115                 plane[2] = r_refdef.view.clipplane.normal[2];
5116                 plane[3] = dist;
5117                 customclipplane = plane;
5118         }
5119
5120         if (!r_refdef.view.useperspective)
5121                 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);
5122         else if (vid.stencil && r_useinfinitefarclip.integer)
5123                 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);
5124         else
5125                 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);
5126         R_SetViewport(&r_refdef.view.viewport);
5127 }
5128
5129 void R_EntityMatrix(const matrix4x4_t *matrix)
5130 {
5131         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5132         {
5133                 gl_modelmatrixchanged = false;
5134                 gl_modelmatrix = *matrix;
5135                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5136                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5137                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5138                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5139                 CHECKGLERROR
5140                 switch(vid.renderpath)
5141                 {
5142                 case RENDERPATH_D3D9:
5143 #ifdef SUPPORTD3D
5144                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5145                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5146 #endif
5147                         break;
5148                 case RENDERPATH_D3D10:
5149                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5150                         break;
5151                 case RENDERPATH_D3D11:
5152                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5153                         break;
5154                 case RENDERPATH_GL13:
5155                 case RENDERPATH_GL11:
5156                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5157                         break;
5158                 case RENDERPATH_SOFT:
5159                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5160                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5161                         break;
5162                 case RENDERPATH_GL20:
5163                 case RENDERPATH_GLES2:
5164                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5165                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5166                         break;
5167                 }
5168         }
5169 }
5170
5171 void R_ResetViewRendering2D(void)
5172 {
5173         r_viewport_t viewport;
5174         DrawQ_Finish();
5175
5176         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5177         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);
5178         R_SetViewport(&viewport);
5179         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5180         GL_Color(1, 1, 1, 1);
5181         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5182         GL_BlendFunc(GL_ONE, GL_ZERO);
5183         GL_ScissorTest(false);
5184         GL_DepthMask(false);
5185         GL_DepthRange(0, 1);
5186         GL_DepthTest(false);
5187         GL_DepthFunc(GL_LEQUAL);
5188         R_EntityMatrix(&identitymatrix);
5189         R_Mesh_ResetTextureState();
5190         GL_PolygonOffset(0, 0);
5191         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5192         switch(vid.renderpath)
5193         {
5194         case RENDERPATH_GL11:
5195         case RENDERPATH_GL13:
5196         case RENDERPATH_GL20:
5197         case RENDERPATH_GLES2:
5198                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5199                 break;
5200         case RENDERPATH_D3D9:
5201         case RENDERPATH_D3D10:
5202         case RENDERPATH_D3D11:
5203         case RENDERPATH_SOFT:
5204                 break;
5205         }
5206         GL_CullFace(GL_NONE);
5207 }
5208
5209 void R_ResetViewRendering3D(void)
5210 {
5211         DrawQ_Finish();
5212
5213         R_SetupView(true);
5214         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5215         GL_Color(1, 1, 1, 1);
5216         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5217         GL_BlendFunc(GL_ONE, GL_ZERO);
5218         GL_ScissorTest(true);
5219         GL_DepthMask(true);
5220         GL_DepthRange(0, 1);
5221         GL_DepthTest(true);
5222         GL_DepthFunc(GL_LEQUAL);
5223         R_EntityMatrix(&identitymatrix);
5224         R_Mesh_ResetTextureState();
5225         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5226         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5227         switch(vid.renderpath)
5228         {
5229         case RENDERPATH_GL11:
5230         case RENDERPATH_GL13:
5231         case RENDERPATH_GL20:
5232         case RENDERPATH_GLES2:
5233                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5234                 break;
5235         case RENDERPATH_D3D9:
5236         case RENDERPATH_D3D10:
5237         case RENDERPATH_D3D11:
5238         case RENDERPATH_SOFT:
5239                 break;
5240         }
5241         GL_CullFace(r_refdef.view.cullface_back);
5242 }
5243
5244 /*
5245 ================
5246 R_RenderView_UpdateViewVectors
5247 ================
5248 */
5249 static void R_RenderView_UpdateViewVectors(void)
5250 {
5251         // break apart the view matrix into vectors for various purposes
5252         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5253         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5254         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5255         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5256         // make an inverted copy of the view matrix for tracking sprites
5257         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5258 }
5259
5260 void R_RenderScene(void);
5261 void R_RenderWaterPlanes(void);
5262
5263 static void R_Water_StartFrame(void)
5264 {
5265         int i;
5266         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5267         r_waterstate_waterplane_t *p;
5268
5269         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5270                 return;
5271
5272         switch(vid.renderpath)
5273         {
5274         case RENDERPATH_GL20:
5275         case RENDERPATH_D3D9:
5276         case RENDERPATH_D3D10:
5277         case RENDERPATH_D3D11:
5278         case RENDERPATH_SOFT:
5279         case RENDERPATH_GLES2:
5280                 break;
5281         case RENDERPATH_GL13:
5282         case RENDERPATH_GL11:
5283                 return;
5284         }
5285
5286         // set waterwidth and waterheight to the water resolution that will be
5287         // used (often less than the screen resolution for faster rendering)
5288         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5289         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5290
5291         // calculate desired texture sizes
5292         // can't use water if the card does not support the texture size
5293         if (!r_water.integer || r_showsurfaces.integer)
5294                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5295         else if (vid.support.arb_texture_non_power_of_two)
5296         {
5297                 texturewidth = waterwidth;
5298                 textureheight = waterheight;
5299                 camerawidth = waterwidth;
5300                 cameraheight = waterheight;
5301         }
5302         else
5303         {
5304                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5305                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5306                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5307                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5308         }
5309
5310         // allocate textures as needed
5311         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5312         {
5313                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5314                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5315                 {
5316                         if (p->texture_refraction)
5317                                 R_FreeTexture(p->texture_refraction);
5318                         p->texture_refraction = NULL;
5319                         if (p->texture_reflection)
5320                                 R_FreeTexture(p->texture_reflection);
5321                         p->texture_reflection = NULL;
5322                         if (p->texture_camera)
5323                                 R_FreeTexture(p->texture_camera);
5324                         p->texture_camera = NULL;
5325                 }
5326                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5327                 r_waterstate.texturewidth = texturewidth;
5328                 r_waterstate.textureheight = textureheight;
5329                 r_waterstate.camerawidth = camerawidth;
5330                 r_waterstate.cameraheight = cameraheight;
5331         }
5332
5333         if (r_waterstate.texturewidth)
5334         {
5335                 r_waterstate.enabled = true;
5336
5337                 // when doing a reduced render (HDR) we want to use a smaller area
5338                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5339                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5340
5341                 // set up variables that will be used in shader setup
5342                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5343                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5344                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5345                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5346         }
5347
5348         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5349         r_waterstate.numwaterplanes = 0;
5350 }
5351
5352 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5353 {
5354         int triangleindex, planeindex;
5355         const int *e;
5356         vec3_t vert[3];
5357         vec3_t normal;
5358         vec3_t center;
5359         mplane_t plane;
5360         r_waterstate_waterplane_t *p;
5361         texture_t *t = R_GetCurrentTexture(surface->texture);
5362
5363         // just use the first triangle with a valid normal for any decisions
5364         VectorClear(normal);
5365         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5366         {
5367                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5368                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5369                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5370                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5371                 if (VectorLength2(normal) >= 0.001)
5372                         break;
5373         }
5374
5375         VectorCopy(normal, plane.normal);
5376         VectorNormalize(plane.normal);
5377         plane.dist = DotProduct(vert[0], plane.normal);
5378         PlaneClassify(&plane);
5379         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5380         {
5381                 // skip backfaces (except if nocullface is set)
5382                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5383                         return;
5384                 VectorNegate(plane.normal, plane.normal);
5385                 plane.dist *= -1;
5386                 PlaneClassify(&plane);
5387         }
5388
5389
5390         // find a matching plane if there is one
5391         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5392                 if(p->camera_entity == t->camera_entity)
5393                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5394                                 break;
5395         if (planeindex >= r_waterstate.maxwaterplanes)
5396                 return; // nothing we can do, out of planes
5397
5398         // if this triangle does not fit any known plane rendered this frame, add one
5399         if (planeindex >= r_waterstate.numwaterplanes)
5400         {
5401                 // store the new plane
5402                 r_waterstate.numwaterplanes++;
5403                 p->plane = plane;
5404                 // clear materialflags and pvs
5405                 p->materialflags = 0;
5406                 p->pvsvalid = false;
5407                 p->camera_entity = t->camera_entity;
5408                 VectorCopy(surface->mins, p->mins);
5409                 VectorCopy(surface->maxs, p->maxs);
5410         }
5411         else
5412         {
5413                 // merge mins/maxs
5414                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5415                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5416                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5417                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5418                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5419                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5420         }
5421         // merge this surface's materialflags into the waterplane
5422         p->materialflags |= t->currentmaterialflags;
5423         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5424         {
5425                 // merge this surface's PVS into the waterplane
5426                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5427                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5428                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5429                 {
5430                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5431                         p->pvsvalid = true;
5432                 }
5433         }
5434 }
5435
5436 static void R_Water_ProcessPlanes(void)
5437 {
5438         int myscissor[4];
5439         r_refdef_view_t originalview;
5440         r_refdef_view_t myview;
5441         int planeindex;
5442         r_waterstate_waterplane_t *p;
5443         vec3_t visorigin;
5444
5445         originalview = r_refdef.view;
5446
5447         // make sure enough textures are allocated
5448         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5449         {
5450                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5451                 {
5452                         if (!p->texture_refraction)
5453                                 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);
5454                         if (!p->texture_refraction)
5455                                 goto error;
5456                 }
5457                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5458                 {
5459                         if (!p->texture_camera)
5460                                 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);
5461                         if (!p->texture_camera)
5462                                 goto error;
5463                 }
5464
5465                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5466                 {
5467                         if (!p->texture_reflection)
5468                                 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);
5469                         if (!p->texture_reflection)
5470                                 goto error;
5471                 }
5472         }
5473
5474         // render views
5475         r_refdef.view = originalview;
5476         r_refdef.view.showdebug = false;
5477         r_refdef.view.width = r_waterstate.waterwidth;
5478         r_refdef.view.height = r_waterstate.waterheight;
5479         r_refdef.view.useclipplane = true;
5480         myview = r_refdef.view;
5481         r_waterstate.renderingscene = true;
5482         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5483         {
5484                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5485                 {
5486                         r_refdef.view = myview;
5487                         if(r_water_scissormode.integer)
5488                         {
5489                                 R_SetupView(true);
5490                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5491                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5492                         }
5493
5494                         // render reflected scene and copy into texture
5495                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5496                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5497                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5498                         r_refdef.view.clipplane = p->plane;
5499
5500                         // reverse the cullface settings for this render
5501                         r_refdef.view.cullface_front = GL_FRONT;
5502                         r_refdef.view.cullface_back = GL_BACK;
5503                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5504                         {
5505                                 r_refdef.view.usecustompvs = true;
5506                                 if (p->pvsvalid)
5507                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5508                                 else
5509                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5510                         }
5511
5512                         R_ResetViewRendering3D();
5513                         R_ClearScreen(r_refdef.fogenabled);
5514                         if(r_water_scissormode.integer & 2)
5515                                 R_View_UpdateWithScissor(myscissor);
5516                         else
5517                                 R_View_Update();
5518                         if(r_water_scissormode.integer & 1)
5519                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5520                         R_RenderScene();
5521
5522                         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);
5523                 }
5524
5525                 // render the normal view scene and copy into texture
5526                 // (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)
5527                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5528                 {
5529                         r_refdef.view = myview;
5530                         if(r_water_scissormode.integer)
5531                         {
5532                                 R_SetupView(true);
5533                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5534                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5535                         }
5536
5537                         r_waterstate.renderingrefraction = true;
5538
5539                         r_refdef.view.clipplane = p->plane;
5540                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5541                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5542
5543                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5544                         {
5545                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5546                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5547                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5548                                 R_RenderView_UpdateViewVectors();
5549                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5550                                 {
5551                                         r_refdef.view.usecustompvs = true;
5552                                         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);
5553                                 }
5554                         }
5555
5556                         PlaneClassify(&r_refdef.view.clipplane);
5557
5558                         R_ResetViewRendering3D();
5559                         R_ClearScreen(r_refdef.fogenabled);
5560                         if(r_water_scissormode.integer & 2)
5561                                 R_View_UpdateWithScissor(myscissor);
5562                         else
5563                                 R_View_Update();
5564                         if(r_water_scissormode.integer & 1)
5565                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5566                         R_RenderScene();
5567
5568                         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);
5569                         r_waterstate.renderingrefraction = false;
5570                 }
5571                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5572                 {
5573                         r_refdef.view = myview;
5574
5575                         r_refdef.view.clipplane = p->plane;
5576                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5577                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5578
5579                         r_refdef.view.width = r_waterstate.camerawidth;
5580                         r_refdef.view.height = r_waterstate.cameraheight;
5581                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5582                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5583
5584                         if(p->camera_entity)
5585                         {
5586                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5587                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5588                         }
5589
5590                         // note: all of the view is used for displaying... so
5591                         // there is no use in scissoring
5592
5593                         // reverse the cullface settings for this render
5594                         r_refdef.view.cullface_front = GL_FRONT;
5595                         r_refdef.view.cullface_back = GL_BACK;
5596                         // also reverse the view matrix
5597                         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
5598                         R_RenderView_UpdateViewVectors();
5599                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5600                         {
5601                                 r_refdef.view.usecustompvs = true;
5602                                 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);
5603                         }
5604                         
5605                         // camera needs no clipplane
5606                         r_refdef.view.useclipplane = false;
5607
5608                         PlaneClassify(&r_refdef.view.clipplane);
5609
5610                         R_ResetViewRendering3D();
5611                         R_ClearScreen(r_refdef.fogenabled);
5612                         R_View_Update();
5613                         R_RenderScene();
5614
5615                         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);
5616                         r_waterstate.renderingrefraction = false;
5617                 }
5618
5619         }
5620         r_waterstate.renderingscene = false;
5621         r_refdef.view = originalview;
5622         R_ResetViewRendering3D();
5623         R_ClearScreen(r_refdef.fogenabled);
5624         R_View_Update();
5625         return;
5626 error:
5627         r_refdef.view = originalview;
5628         r_waterstate.renderingscene = false;
5629         Cvar_SetValueQuick(&r_water, 0);
5630         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5631         return;
5632 }
5633
5634 void R_Bloom_StartFrame(void)
5635 {
5636         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5637
5638         switch(vid.renderpath)
5639         {
5640         case RENDERPATH_GL20:
5641         case RENDERPATH_D3D9:
5642         case RENDERPATH_D3D10:
5643         case RENDERPATH_D3D11:
5644         case RENDERPATH_SOFT:
5645         case RENDERPATH_GLES2:
5646                 break;
5647         case RENDERPATH_GL13:
5648         case RENDERPATH_GL11:
5649                 return;
5650         }
5651
5652         // set bloomwidth and bloomheight to the bloom resolution that will be
5653         // used (often less than the screen resolution for faster rendering)
5654         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5655         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5656         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5657         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5658         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5659
5660         // calculate desired texture sizes
5661         if (vid.support.arb_texture_non_power_of_two)
5662         {
5663                 screentexturewidth = r_refdef.view.width;
5664                 screentextureheight = r_refdef.view.height;
5665                 bloomtexturewidth = r_bloomstate.bloomwidth;
5666                 bloomtextureheight = r_bloomstate.bloomheight;
5667         }
5668         else
5669         {
5670                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5671                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5672                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5673                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5674         }
5675
5676         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))
5677         {
5678                 Cvar_SetValueQuick(&r_hdr, 0);
5679                 Cvar_SetValueQuick(&r_bloom, 0);
5680                 Cvar_SetValueQuick(&r_motionblur, 0);
5681                 Cvar_SetValueQuick(&r_damageblur, 0);
5682         }
5683
5684         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)))
5685                 screentexturewidth = screentextureheight = 0;
5686         if (!r_hdr.integer && !r_bloom.integer)
5687                 bloomtexturewidth = bloomtextureheight = 0;
5688
5689         // allocate textures as needed
5690         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5691         {
5692                 if (r_bloomstate.texture_screen)
5693                         R_FreeTexture(r_bloomstate.texture_screen);
5694                 r_bloomstate.texture_screen = NULL;
5695                 r_bloomstate.screentexturewidth = screentexturewidth;
5696                 r_bloomstate.screentextureheight = screentextureheight;
5697                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5698                         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);
5699         }
5700         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5701         {
5702                 if (r_bloomstate.texture_bloom)
5703                         R_FreeTexture(r_bloomstate.texture_bloom);
5704                 r_bloomstate.texture_bloom = NULL;
5705                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5706                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5707                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5708                         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);
5709         }
5710
5711         // when doing a reduced render (HDR) we want to use a smaller area
5712         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5713         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5714         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5715         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5716         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5717
5718         // set up a texcoord array for the full resolution screen image
5719         // (we have to keep this around to copy back during final render)
5720         r_bloomstate.screentexcoord2f[0] = 0;
5721         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5722         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5723         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5724         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5725         r_bloomstate.screentexcoord2f[5] = 0;
5726         r_bloomstate.screentexcoord2f[6] = 0;
5727         r_bloomstate.screentexcoord2f[7] = 0;
5728
5729         // set up a texcoord array for the reduced resolution bloom image
5730         // (which will be additive blended over the screen image)
5731         r_bloomstate.bloomtexcoord2f[0] = 0;
5732         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5733         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5734         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5735         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5736         r_bloomstate.bloomtexcoord2f[5] = 0;
5737         r_bloomstate.bloomtexcoord2f[6] = 0;
5738         r_bloomstate.bloomtexcoord2f[7] = 0;
5739
5740         switch(vid.renderpath)
5741         {
5742         case RENDERPATH_GL11:
5743         case RENDERPATH_GL13:
5744         case RENDERPATH_GL20:
5745         case RENDERPATH_SOFT:
5746         case RENDERPATH_GLES2:
5747                 break;
5748         case RENDERPATH_D3D9:
5749         case RENDERPATH_D3D10:
5750         case RENDERPATH_D3D11:
5751                 {
5752                         int i;
5753                         for (i = 0;i < 4;i++)
5754                         {
5755                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5756                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5757                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5758                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5759                         }
5760                 }
5761                 break;
5762         }
5763
5764         if (r_hdr.integer || r_bloom.integer)
5765         {
5766                 r_bloomstate.enabled = true;
5767                 r_bloomstate.hdr = r_hdr.integer != 0;
5768         }
5769
5770         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);
5771 }
5772
5773 void R_Bloom_CopyBloomTexture(float colorscale)
5774 {
5775         r_refdef.stats.bloom++;
5776
5777         // scale down screen texture to the bloom texture size
5778         CHECKGLERROR
5779         R_SetViewport(&r_bloomstate.viewport);
5780         GL_BlendFunc(GL_ONE, GL_ZERO);
5781         GL_Color(colorscale, colorscale, colorscale, 1);
5782         // 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...
5783         switch(vid.renderpath)
5784         {
5785         case RENDERPATH_GL11:
5786         case RENDERPATH_GL13:
5787         case RENDERPATH_GL20:
5788         case RENDERPATH_SOFT:
5789         case RENDERPATH_GLES2:
5790                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5791                 break;
5792         case RENDERPATH_D3D9:
5793         case RENDERPATH_D3D10:
5794         case RENDERPATH_D3D11:
5795                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5796                 break;
5797         }
5798         // TODO: do boxfilter scale-down in shader?
5799         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5800         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5801         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5802
5803         // we now have a bloom image in the framebuffer
5804         // copy it into the bloom image texture for later processing
5805         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);
5806         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5807 }
5808
5809 void R_Bloom_CopyHDRTexture(void)
5810 {
5811         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);
5812         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5813 }
5814
5815 void R_Bloom_MakeTexture(void)
5816 {
5817         int x, range, dir;
5818         float xoffset, yoffset, r, brighten;
5819
5820         r_refdef.stats.bloom++;
5821
5822         R_ResetViewRendering2D();
5823
5824         // we have a bloom image in the framebuffer
5825         CHECKGLERROR
5826         R_SetViewport(&r_bloomstate.viewport);
5827
5828         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5829         {
5830                 x *= 2;
5831                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5832                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5833                 GL_Color(r,r,r,1);
5834                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5835                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5836                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5837                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5838
5839                 // copy the vertically blurred bloom view to a texture
5840                 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);
5841                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5842         }
5843
5844         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5845         brighten = r_bloom_brighten.value;
5846         if (r_hdr.integer)
5847                 brighten *= r_hdr_range.value;
5848         brighten = sqrt(brighten);
5849         if(range >= 1)
5850                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5851         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5852
5853         for (dir = 0;dir < 2;dir++)
5854         {
5855                 // blend on at multiple vertical offsets to achieve a vertical blur
5856                 // TODO: do offset blends using GLSL
5857                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5858                 GL_BlendFunc(GL_ONE, GL_ZERO);
5859                 for (x = -range;x <= range;x++)
5860                 {
5861                         if (!dir){xoffset = 0;yoffset = x;}
5862                         else {xoffset = x;yoffset = 0;}
5863                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5864                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5865                         // compute a texcoord array with the specified x and y offset
5866                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5867                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5868                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5869                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5870                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5871                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5872                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5873                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5874                         // this r value looks like a 'dot' particle, fading sharply to
5875                         // black at the edges
5876                         // (probably not realistic but looks good enough)
5877                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5878                         //r = brighten/(range*2+1);
5879                         r = brighten / (range * 2 + 1);
5880                         if(range >= 1)
5881                                 r *= (1 - x*x/(float)(range*range));
5882                         GL_Color(r, r, r, 1);
5883                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5884                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5885                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5886                         GL_BlendFunc(GL_ONE, GL_ONE);
5887                 }
5888
5889                 // copy the vertically blurred bloom view to a texture
5890                 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);
5891                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5892         }
5893 }
5894
5895 void R_HDR_RenderBloomTexture(void)
5896 {
5897         int oldwidth, oldheight;
5898         float oldcolorscale;
5899         qboolean oldwaterstate;
5900
5901         oldwaterstate = r_waterstate.enabled;
5902         oldcolorscale = r_refdef.view.colorscale;
5903         oldwidth = r_refdef.view.width;
5904         oldheight = r_refdef.view.height;
5905         r_refdef.view.width = r_bloomstate.bloomwidth;
5906         r_refdef.view.height = r_bloomstate.bloomheight;
5907
5908         if(r_hdr.integer < 2)
5909                 r_waterstate.enabled = false;
5910
5911         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5912         // TODO: add exposure compensation features
5913         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5914
5915         r_refdef.view.showdebug = false;
5916         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5917
5918         R_ResetViewRendering3D();
5919
5920         R_ClearScreen(r_refdef.fogenabled);
5921         if (r_timereport_active)
5922                 R_TimeReport("HDRclear");
5923
5924         R_View_Update();
5925         if (r_timereport_active)
5926                 R_TimeReport("visibility");
5927
5928         // only do secondary renders with HDR if r_hdr is 2 or higher
5929         r_waterstate.numwaterplanes = 0;
5930         if (r_waterstate.enabled)
5931                 R_RenderWaterPlanes();
5932
5933         r_refdef.view.showdebug = true;
5934         R_RenderScene();
5935         r_waterstate.numwaterplanes = 0;
5936
5937         R_ResetViewRendering2D();
5938
5939         R_Bloom_CopyHDRTexture();
5940         R_Bloom_MakeTexture();
5941
5942         // restore the view settings
5943         r_waterstate.enabled = oldwaterstate;
5944         r_refdef.view.width = oldwidth;
5945         r_refdef.view.height = oldheight;
5946         r_refdef.view.colorscale = oldcolorscale;
5947
5948         R_ResetViewRendering3D();
5949
5950         R_ClearScreen(r_refdef.fogenabled);
5951         if (r_timereport_active)
5952                 R_TimeReport("viewclear");
5953 }
5954
5955 static void R_BlendView(void)
5956 {
5957         unsigned int permutation;
5958         float uservecs[4][4];
5959
5960         switch (vid.renderpath)
5961         {
5962         case RENDERPATH_GL20:
5963         case RENDERPATH_D3D9:
5964         case RENDERPATH_D3D10:
5965         case RENDERPATH_D3D11:
5966         case RENDERPATH_SOFT:
5967         case RENDERPATH_GLES2:
5968                 permutation =
5969                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5970                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5971                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5972                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5973                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5974
5975                 if (r_bloomstate.texture_screen)
5976                 {
5977                         // make sure the buffer is available
5978                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5979
5980                         R_ResetViewRendering2D();
5981
5982                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5983                         {
5984                                 // declare variables
5985                                 float speed;
5986                                 static float avgspeed;
5987
5988                                 speed = VectorLength(cl.movement_velocity);
5989
5990                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5991                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5992
5993                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5994                                 speed = bound(0, speed, 1);
5995                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5996
5997                                 // calculate values into a standard alpha
5998                                 cl.motionbluralpha = 1 - exp(-
5999                                                 (
6000                                                  (r_motionblur.value * speed / 80)
6001                                                  +
6002                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6003                                                 )
6004                                                 /
6005                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6006                                            );
6007
6008                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6009                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6010                                 // apply the blur
6011                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6012                                 {
6013                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6014                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6015                                         switch(vid.renderpath)
6016                                         {
6017                                         case RENDERPATH_GL11:
6018                                         case RENDERPATH_GL13:
6019                                         case RENDERPATH_GL20:
6020                                         case RENDERPATH_SOFT:
6021                                         case RENDERPATH_GLES2:
6022                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6023                                                 break;
6024                                         case RENDERPATH_D3D9:
6025                                         case RENDERPATH_D3D10:
6026                                         case RENDERPATH_D3D11:
6027                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6028                                                 break;
6029                                         }
6030                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6031                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6032                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6033                                 }
6034                         }
6035
6036                         // copy view into the screen texture
6037                         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);
6038                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6039                 }
6040                 else if (!r_bloomstate.texture_bloom)
6041                 {
6042                         // we may still have to do view tint...
6043                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6044                         {
6045                                 // apply a color tint to the whole view
6046                                 R_ResetViewRendering2D();
6047                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6048                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6049                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6050                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6051                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6052                         }
6053                         break; // no screen processing, no bloom, skip it
6054                 }
6055
6056                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6057                 {
6058                         // render simple bloom effect
6059                         // copy the screen and shrink it and darken it for the bloom process
6060                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6061                         // make the bloom texture
6062                         R_Bloom_MakeTexture();
6063                 }
6064
6065 #if _MSC_VER >= 1400
6066 #define sscanf sscanf_s
6067 #endif
6068                 memset(uservecs, 0, sizeof(uservecs));
6069                 if (r_glsl_postprocess_uservec1_enable.integer)
6070                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6071                 if (r_glsl_postprocess_uservec2_enable.integer)
6072                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6073                 if (r_glsl_postprocess_uservec3_enable.integer)
6074                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6075                 if (r_glsl_postprocess_uservec4_enable.integer)
6076                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6077
6078                 R_ResetViewRendering2D();
6079                 GL_Color(1, 1, 1, 1);
6080                 GL_BlendFunc(GL_ONE, GL_ZERO);
6081
6082                 switch(vid.renderpath)
6083                 {
6084                 case RENDERPATH_GL20:
6085                 case RENDERPATH_GLES2:
6086                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6087                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6088                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6089                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6090                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6091                         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]);
6092                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6093                         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]);
6094                         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]);
6095                         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]);
6096                         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]);
6097                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6098                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6099                         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);
6100                         break;
6101                 case RENDERPATH_D3D9:
6102 #ifdef SUPPORTD3D
6103                         // 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...
6104                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6105                         R_SetupShader_SetPermutationHLSL(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                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6110                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6111                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6112                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6113                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6114                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6115                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6116                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6117                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6118 #endif
6119                         break;
6120                 case RENDERPATH_D3D10:
6121                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6122                         break;
6123                 case RENDERPATH_D3D11:
6124                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6125                         break;
6126                 case RENDERPATH_SOFT:
6127                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6128                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6129                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6130                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6131                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6132                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6133                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6134                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6135                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6136                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6137                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6138                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6139                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6140                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6141                         break;
6142                 default:
6143                         break;
6144                 }
6145                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6146                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6147                 break;
6148         case RENDERPATH_GL13:
6149         case RENDERPATH_GL11:
6150                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6151                 {
6152                         // apply a color tint to the whole view
6153                         R_ResetViewRendering2D();
6154                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6155                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6156                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6157                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6158                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6159                 }
6160                 break;
6161         }
6162 }
6163
6164 matrix4x4_t r_waterscrollmatrix;
6165
6166 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6167 {
6168         if (r_refdef.fog_density)
6169         {
6170                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6171                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6172                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6173
6174                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6175                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6176                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6177                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6178
6179                 {
6180                         vec3_t fogvec;
6181                         VectorCopy(r_refdef.fogcolor, fogvec);
6182                         //   color.rgb *= ContrastBoost * SceneBrightness;
6183                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6184                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6185                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6186                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6187                 }
6188         }
6189 }
6190
6191 void R_UpdateVariables(void)
6192 {
6193         R_Textures_Frame();
6194
6195         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6196
6197         r_refdef.farclip = r_farclip_base.value;
6198         if (r_refdef.scene.worldmodel)
6199                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6200         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6201
6202         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6203                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6204         r_refdef.polygonfactor = 0;
6205         r_refdef.polygonoffset = 0;
6206         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6207         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6208
6209         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6210         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6211         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6212         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6213         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6214         if (FAKELIGHT_ENABLED)
6215         {
6216                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6217         }
6218         if (r_showsurfaces.integer)
6219         {
6220                 r_refdef.scene.rtworld = false;
6221                 r_refdef.scene.rtworldshadows = false;
6222                 r_refdef.scene.rtdlight = false;
6223                 r_refdef.scene.rtdlightshadows = false;
6224                 r_refdef.lightmapintensity = 0;
6225         }
6226
6227         if (gamemode == GAME_NEHAHRA)
6228         {
6229                 if (gl_fogenable.integer)
6230                 {
6231                         r_refdef.oldgl_fogenable = true;
6232                         r_refdef.fog_density = gl_fogdensity.value;
6233                         r_refdef.fog_red = gl_fogred.value;
6234                         r_refdef.fog_green = gl_foggreen.value;
6235                         r_refdef.fog_blue = gl_fogblue.value;
6236                         r_refdef.fog_alpha = 1;
6237                         r_refdef.fog_start = 0;
6238                         r_refdef.fog_end = gl_skyclip.value;
6239                         r_refdef.fog_height = 1<<30;
6240                         r_refdef.fog_fadedepth = 128;
6241                 }
6242                 else if (r_refdef.oldgl_fogenable)
6243                 {
6244                         r_refdef.oldgl_fogenable = false;
6245                         r_refdef.fog_density = 0;
6246                         r_refdef.fog_red = 0;
6247                         r_refdef.fog_green = 0;
6248                         r_refdef.fog_blue = 0;
6249                         r_refdef.fog_alpha = 0;
6250                         r_refdef.fog_start = 0;
6251                         r_refdef.fog_end = 0;
6252                         r_refdef.fog_height = 1<<30;
6253                         r_refdef.fog_fadedepth = 128;
6254                 }
6255         }
6256
6257         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6258         r_refdef.fog_start = max(0, r_refdef.fog_start);
6259         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6260
6261         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6262
6263         if (r_refdef.fog_density && r_drawfog.integer)
6264         {
6265                 r_refdef.fogenabled = true;
6266                 // this is the point where the fog reaches 0.9986 alpha, which we
6267                 // consider a good enough cutoff point for the texture
6268                 // (0.9986 * 256 == 255.6)
6269                 if (r_fog_exp2.integer)
6270                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6271                 else
6272                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6273                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6274                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6275                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6276                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6277                         R_BuildFogHeightTexture();
6278                 // fog color was already set
6279                 // update the fog texture
6280                 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)
6281                         R_BuildFogTexture();
6282                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6283                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6284         }
6285         else
6286                 r_refdef.fogenabled = false;
6287
6288         switch(vid.renderpath)
6289         {
6290         case RENDERPATH_GL20:
6291         case RENDERPATH_D3D9:
6292         case RENDERPATH_D3D10:
6293         case RENDERPATH_D3D11:
6294         case RENDERPATH_SOFT:
6295         case RENDERPATH_GLES2:
6296                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6297                 {
6298                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6299                         {
6300                                 // build GLSL gamma texture
6301 #define RAMPWIDTH 256
6302                                 unsigned short ramp[RAMPWIDTH * 3];
6303                                 unsigned char rampbgr[RAMPWIDTH][4];
6304                                 int i;
6305
6306                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6307
6308                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6309                                 for(i = 0; i < RAMPWIDTH; ++i)
6310                                 {
6311                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6312                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6313                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6314                                         rampbgr[i][3] = 0;
6315                                 }
6316                                 if (r_texture_gammaramps)
6317                                 {
6318                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6319                                 }
6320                                 else
6321                                 {
6322                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6323                                 }
6324                         }
6325                 }
6326                 else
6327                 {
6328                         // remove GLSL gamma texture
6329                 }
6330                 break;
6331         case RENDERPATH_GL13:
6332         case RENDERPATH_GL11:
6333                 break;
6334         }
6335 }
6336
6337 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6338 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6339 /*
6340 ================
6341 R_SelectScene
6342 ================
6343 */
6344 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6345         if( scenetype != r_currentscenetype ) {
6346                 // store the old scenetype
6347                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6348                 r_currentscenetype = scenetype;
6349                 // move in the new scene
6350                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6351         }
6352 }
6353
6354 /*
6355 ================
6356 R_GetScenePointer
6357 ================
6358 */
6359 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6360 {
6361         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6362         if( scenetype == r_currentscenetype ) {
6363                 return &r_refdef.scene;
6364         } else {
6365                 return &r_scenes_store[ scenetype ];
6366         }
6367 }
6368
6369 /*
6370 ================
6371 R_RenderView
6372 ================
6373 */
6374 int dpsoftrast_test;
6375 void R_RenderView(void)
6376 {
6377         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6378
6379         dpsoftrast_test = r_test.integer;
6380
6381         if (r_timereport_active)
6382                 R_TimeReport("start");
6383         r_textureframe++; // used only by R_GetCurrentTexture
6384         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6385
6386         if(R_CompileShader_CheckStaticParms())
6387                 R_GLSL_Restart_f();
6388
6389         if (!r_drawentities.integer)
6390                 r_refdef.scene.numentities = 0;
6391
6392         R_AnimCache_ClearCache();
6393         R_FrameData_NewFrame();
6394
6395         /* adjust for stereo display */
6396         if(R_Stereo_Active())
6397         {
6398                 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);
6399                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6400         }
6401
6402         if (r_refdef.view.isoverlay)
6403         {
6404                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6405                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6406                 R_TimeReport("depthclear");
6407
6408                 r_refdef.view.showdebug = false;
6409
6410                 r_waterstate.enabled = false;
6411                 r_waterstate.numwaterplanes = 0;
6412
6413                 R_RenderScene();
6414
6415                 r_refdef.view.matrix = originalmatrix;
6416
6417                 CHECKGLERROR
6418                 return;
6419         }
6420
6421         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6422         {
6423                 r_refdef.view.matrix = originalmatrix;
6424                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6425         }
6426
6427         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6428
6429         R_RenderView_UpdateViewVectors();
6430
6431         R_Shadow_UpdateWorldLightSelection();
6432
6433         R_Bloom_StartFrame();
6434         R_Water_StartFrame();
6435
6436         CHECKGLERROR
6437         if (r_timereport_active)
6438                 R_TimeReport("viewsetup");
6439
6440         R_ResetViewRendering3D();
6441
6442         if (r_refdef.view.clear || r_refdef.fogenabled)
6443         {
6444                 R_ClearScreen(r_refdef.fogenabled);
6445                 if (r_timereport_active)
6446                         R_TimeReport("viewclear");
6447         }
6448         r_refdef.view.clear = true;
6449
6450         // this produces a bloom texture to be used in R_BlendView() later
6451         if (r_hdr.integer && r_bloomstate.bloomwidth)
6452         {
6453                 R_HDR_RenderBloomTexture();
6454                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6455                 r_textureframe++; // used only by R_GetCurrentTexture
6456         }
6457
6458         r_refdef.view.showdebug = true;
6459
6460         R_View_Update();
6461         if (r_timereport_active)
6462                 R_TimeReport("visibility");
6463
6464         r_waterstate.numwaterplanes = 0;
6465         if (r_waterstate.enabled)
6466                 R_RenderWaterPlanes();
6467
6468         R_RenderScene();
6469         r_waterstate.numwaterplanes = 0;
6470
6471         R_BlendView();
6472         if (r_timereport_active)
6473                 R_TimeReport("blendview");
6474
6475         GL_Scissor(0, 0, vid.width, vid.height);
6476         GL_ScissorTest(false);
6477
6478         r_refdef.view.matrix = originalmatrix;
6479
6480         CHECKGLERROR
6481 }
6482
6483 void R_RenderWaterPlanes(void)
6484 {
6485         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6486         {
6487                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6488                 if (r_timereport_active)
6489                         R_TimeReport("waterworld");
6490         }
6491
6492         // don't let sound skip if going slow
6493         if (r_refdef.scene.extraupdate)
6494                 S_ExtraUpdate ();
6495
6496         R_DrawModelsAddWaterPlanes();
6497         if (r_timereport_active)
6498                 R_TimeReport("watermodels");
6499
6500         if (r_waterstate.numwaterplanes)
6501         {
6502                 R_Water_ProcessPlanes();
6503                 if (r_timereport_active)
6504                         R_TimeReport("waterscenes");
6505         }
6506 }
6507
6508 extern void R_DrawLightningBeams (void);
6509 extern void VM_CL_AddPolygonsToMeshQueue (void);
6510 extern void R_DrawPortals (void);
6511 extern cvar_t cl_locs_show;
6512 static void R_DrawLocs(void);
6513 static void R_DrawEntityBBoxes(void);
6514 static void R_DrawModelDecals(void);
6515 extern void R_DrawModelShadows(void);
6516 extern void R_DrawModelShadowMaps(void);
6517 extern cvar_t cl_decals_newsystem;
6518 extern qboolean r_shadow_usingdeferredprepass;
6519 void R_RenderScene(void)
6520 {
6521         qboolean shadowmapping = false;
6522
6523         if (r_timereport_active)
6524                 R_TimeReport("beginscene");
6525
6526         r_refdef.stats.renders++;
6527
6528         R_UpdateFogColor();
6529
6530         // don't let sound skip if going slow
6531         if (r_refdef.scene.extraupdate)
6532                 S_ExtraUpdate ();
6533
6534         R_MeshQueue_BeginScene();
6535
6536         R_SkyStartFrame();
6537
6538         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);
6539
6540         if (r_timereport_active)
6541                 R_TimeReport("skystartframe");
6542
6543         if (cl.csqc_vidvars.drawworld)
6544         {
6545                 // don't let sound skip if going slow
6546                 if (r_refdef.scene.extraupdate)
6547                         S_ExtraUpdate ();
6548
6549                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6550                 {
6551                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6552                         if (r_timereport_active)
6553                                 R_TimeReport("worldsky");
6554                 }
6555
6556                 if (R_DrawBrushModelsSky() && r_timereport_active)
6557                         R_TimeReport("bmodelsky");
6558
6559                 if (skyrendermasked && skyrenderlater)
6560                 {
6561                         // we have to force off the water clipping plane while rendering sky
6562                         R_SetupView(false);
6563                         R_Sky();
6564                         R_SetupView(true);
6565                         if (r_timereport_active)
6566                                 R_TimeReport("sky");
6567                 }
6568         }
6569
6570         R_AnimCache_CacheVisibleEntities();
6571         if (r_timereport_active)
6572                 R_TimeReport("animation");
6573
6574         R_Shadow_PrepareLights();
6575         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6576                 R_Shadow_PrepareModelShadows();
6577         if (r_timereport_active)
6578                 R_TimeReport("preparelights");
6579
6580         if (R_Shadow_ShadowMappingEnabled())
6581                 shadowmapping = true;
6582
6583         if (r_shadow_usingdeferredprepass)
6584                 R_Shadow_DrawPrepass();
6585
6586         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6587         {
6588                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6589                 if (r_timereport_active)
6590                         R_TimeReport("worlddepth");
6591         }
6592         if (r_depthfirst.integer >= 2)
6593         {
6594                 R_DrawModelsDepth();
6595                 if (r_timereport_active)
6596                         R_TimeReport("modeldepth");
6597         }
6598
6599         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6600         {
6601                 R_DrawModelShadowMaps();
6602                 R_ResetViewRendering3D();
6603                 // don't let sound skip if going slow
6604                 if (r_refdef.scene.extraupdate)
6605                         S_ExtraUpdate ();
6606         }
6607
6608         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6609         {
6610                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6611                 if (r_timereport_active)
6612                         R_TimeReport("world");
6613         }
6614
6615         // don't let sound skip if going slow
6616         if (r_refdef.scene.extraupdate)
6617                 S_ExtraUpdate ();
6618
6619         R_DrawModels();
6620         if (r_timereport_active)
6621                 R_TimeReport("models");
6622
6623         // don't let sound skip if going slow
6624         if (r_refdef.scene.extraupdate)
6625                 S_ExtraUpdate ();
6626
6627         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6628         {
6629                 R_DrawModelShadows();
6630                 R_ResetViewRendering3D();
6631                 // don't let sound skip if going slow
6632                 if (r_refdef.scene.extraupdate)
6633                         S_ExtraUpdate ();
6634         }
6635
6636         if (!r_shadow_usingdeferredprepass)
6637         {
6638                 R_Shadow_DrawLights();
6639                 if (r_timereport_active)
6640                         R_TimeReport("rtlights");
6641         }
6642
6643         // don't let sound skip if going slow
6644         if (r_refdef.scene.extraupdate)
6645                 S_ExtraUpdate ();
6646
6647         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6648         {
6649                 R_DrawModelShadows();
6650                 R_ResetViewRendering3D();
6651                 // don't let sound skip if going slow
6652                 if (r_refdef.scene.extraupdate)
6653                         S_ExtraUpdate ();
6654         }
6655
6656         if (cl.csqc_vidvars.drawworld)
6657         {
6658                 if (cl_decals_newsystem.integer)
6659                 {
6660                         R_DrawModelDecals();
6661                         if (r_timereport_active)
6662                                 R_TimeReport("modeldecals");
6663                 }
6664                 else
6665                 {
6666                         R_DrawDecals();
6667                         if (r_timereport_active)
6668                                 R_TimeReport("decals");
6669                 }
6670
6671                 R_DrawParticles();
6672                 if (r_timereport_active)
6673                         R_TimeReport("particles");
6674
6675                 R_DrawExplosions();
6676                 if (r_timereport_active)
6677                         R_TimeReport("explosions");
6678
6679                 R_DrawLightningBeams();
6680                 if (r_timereport_active)
6681                         R_TimeReport("lightning");
6682         }
6683
6684         VM_CL_AddPolygonsToMeshQueue();
6685
6686         if (r_refdef.view.showdebug)
6687         {
6688                 if (cl_locs_show.integer)
6689                 {
6690                         R_DrawLocs();
6691                         if (r_timereport_active)
6692                                 R_TimeReport("showlocs");
6693                 }
6694
6695                 if (r_drawportals.integer)
6696                 {
6697                         R_DrawPortals();
6698                         if (r_timereport_active)
6699                                 R_TimeReport("portals");
6700                 }
6701
6702                 if (r_showbboxes.value > 0)
6703                 {
6704                         R_DrawEntityBBoxes();
6705                         if (r_timereport_active)
6706                                 R_TimeReport("bboxes");
6707                 }
6708         }
6709
6710         R_MeshQueue_RenderTransparent();
6711         if (r_timereport_active)
6712                 R_TimeReport("drawtrans");
6713
6714         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))
6715         {
6716                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6717                 if (r_timereport_active)
6718                         R_TimeReport("worlddebug");
6719                 R_DrawModelsDebug();
6720                 if (r_timereport_active)
6721                         R_TimeReport("modeldebug");
6722         }
6723
6724         if (cl.csqc_vidvars.drawworld)
6725         {
6726                 R_Shadow_DrawCoronas();
6727                 if (r_timereport_active)
6728                         R_TimeReport("coronas");
6729         }
6730
6731 #if 0
6732         {
6733                 GL_DepthTest(false);
6734                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6735                 GL_Color(1, 1, 1, 1);
6736                 qglBegin(GL_POLYGON);
6737                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6738                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6739                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6740                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6741                 qglEnd();
6742                 qglBegin(GL_POLYGON);
6743                 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]);
6744                 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]);
6745                 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]);
6746                 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]);
6747                 qglEnd();
6748                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6749         }
6750 #endif
6751
6752         // don't let sound skip if going slow
6753         if (r_refdef.scene.extraupdate)
6754                 S_ExtraUpdate ();
6755
6756         R_ResetViewRendering2D();
6757 }
6758
6759 static const unsigned short bboxelements[36] =
6760 {
6761         5, 1, 3, 5, 3, 7,
6762         6, 2, 0, 6, 0, 4,
6763         7, 3, 2, 7, 2, 6,
6764         4, 0, 1, 4, 1, 5,
6765         4, 5, 7, 4, 7, 6,
6766         1, 0, 2, 1, 2, 3,
6767 };
6768
6769 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6770 {
6771         int i;
6772         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6773
6774         RSurf_ActiveWorldEntity();
6775
6776         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6777         GL_DepthMask(false);
6778         GL_DepthRange(0, 1);
6779         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6780 //      R_Mesh_ResetTextureState();
6781
6782         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6783         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6784         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6785         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6786         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6787         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6788         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6789         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6790         R_FillColors(color4f, 8, cr, cg, cb, ca);
6791         if (r_refdef.fogenabled)
6792         {
6793                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6794                 {
6795                         f1 = RSurf_FogVertex(v);
6796                         f2 = 1 - f1;
6797                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6798                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6799                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6800                 }
6801         }
6802         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6803         R_Mesh_ResetTextureState();
6804         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6805         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6806 }
6807
6808 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6809 {
6810         int i;
6811         float color[4];
6812         prvm_edict_t *edict;
6813         prvm_prog_t *prog_save = prog;
6814
6815         // this function draws bounding boxes of server entities
6816         if (!sv.active)
6817                 return;
6818
6819         GL_CullFace(GL_NONE);
6820         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6821
6822         prog = 0;
6823         SV_VM_Begin();
6824         for (i = 0;i < numsurfaces;i++)
6825         {
6826                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6827                 switch ((int)edict->fields.server->solid)
6828                 {
6829                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6830                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6831                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6832                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6833                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6834                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6835                 }
6836                 color[3] *= r_showbboxes.value;
6837                 color[3] = bound(0, color[3], 1);
6838                 GL_DepthTest(!r_showdisabledepthtest.integer);
6839                 GL_CullFace(r_refdef.view.cullface_front);
6840                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6841         }
6842         SV_VM_End();
6843         prog = prog_save;
6844 }
6845
6846 static void R_DrawEntityBBoxes(void)
6847 {
6848         int i;
6849         prvm_edict_t *edict;
6850         vec3_t center;
6851         prvm_prog_t *prog_save = prog;
6852
6853         // this function draws bounding boxes of server entities
6854         if (!sv.active)
6855                 return;
6856
6857         prog = 0;
6858         SV_VM_Begin();
6859         for (i = 0;i < prog->num_edicts;i++)
6860         {
6861                 edict = PRVM_EDICT_NUM(i);
6862                 if (edict->priv.server->free)
6863                         continue;
6864                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6865                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6866                         continue;
6867                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6868                         continue;
6869                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6870                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6871         }
6872         SV_VM_End();
6873         prog = prog_save;
6874 }
6875
6876 static const int nomodelelement3i[24] =
6877 {
6878         5, 2, 0,
6879         5, 1, 2,
6880         5, 0, 3,
6881         5, 3, 1,
6882         0, 2, 4,
6883         2, 1, 4,
6884         3, 0, 4,
6885         1, 3, 4
6886 };
6887
6888 static const unsigned short nomodelelement3s[24] =
6889 {
6890         5, 2, 0,
6891         5, 1, 2,
6892         5, 0, 3,
6893         5, 3, 1,
6894         0, 2, 4,
6895         2, 1, 4,
6896         3, 0, 4,
6897         1, 3, 4
6898 };
6899
6900 static const float nomodelvertex3f[6*3] =
6901 {
6902         -16,   0,   0,
6903          16,   0,   0,
6904           0, -16,   0,
6905           0,  16,   0,
6906           0,   0, -16,
6907           0,   0,  16
6908 };
6909
6910 static const float nomodelcolor4f[6*4] =
6911 {
6912         0.0f, 0.0f, 0.5f, 1.0f,
6913         0.0f, 0.0f, 0.5f, 1.0f,
6914         0.0f, 0.5f, 0.0f, 1.0f,
6915         0.0f, 0.5f, 0.0f, 1.0f,
6916         0.5f, 0.0f, 0.0f, 1.0f,
6917         0.5f, 0.0f, 0.0f, 1.0f
6918 };
6919
6920 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6921 {
6922         int i;
6923         float f1, f2, *c;
6924         float color4f[6*4];
6925
6926         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);
6927
6928         // this is only called once per entity so numsurfaces is always 1, and
6929         // surfacelist is always {0}, so this code does not handle batches
6930
6931         if (rsurface.ent_flags & RENDER_ADDITIVE)
6932         {
6933                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6934                 GL_DepthMask(false);
6935         }
6936         else if (rsurface.colormod[3] < 1)
6937         {
6938                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6939                 GL_DepthMask(false);
6940         }
6941         else
6942         {
6943                 GL_BlendFunc(GL_ONE, GL_ZERO);
6944                 GL_DepthMask(true);
6945         }
6946         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6947         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6948         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6949         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6950         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6951         for (i = 0, c = color4f;i < 6;i++, c += 4)
6952         {
6953                 c[0] *= rsurface.colormod[0];
6954                 c[1] *= rsurface.colormod[1];
6955                 c[2] *= rsurface.colormod[2];
6956                 c[3] *= rsurface.colormod[3];
6957         }
6958         if (r_refdef.fogenabled)
6959         {
6960                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6961                 {
6962                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6963                         f2 = 1 - f1;
6964                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6965                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6966                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6967                 }
6968         }
6969 //      R_Mesh_ResetTextureState();
6970         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6971         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6972         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6973 }
6974
6975 void R_DrawNoModel(entity_render_t *ent)
6976 {
6977         vec3_t org;
6978         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6979         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6980                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6981         else
6982                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6983 }
6984
6985 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6986 {
6987         vec3_t right1, right2, diff, normal;
6988
6989         VectorSubtract (org2, org1, normal);
6990
6991         // calculate 'right' vector for start
6992         VectorSubtract (r_refdef.view.origin, org1, diff);
6993         CrossProduct (normal, diff, right1);
6994         VectorNormalize (right1);
6995
6996         // calculate 'right' vector for end
6997         VectorSubtract (r_refdef.view.origin, org2, diff);
6998         CrossProduct (normal, diff, right2);
6999         VectorNormalize (right2);
7000
7001         vert[ 0] = org1[0] + width * right1[0];
7002         vert[ 1] = org1[1] + width * right1[1];
7003         vert[ 2] = org1[2] + width * right1[2];
7004         vert[ 3] = org1[0] - width * right1[0];
7005         vert[ 4] = org1[1] - width * right1[1];
7006         vert[ 5] = org1[2] - width * right1[2];
7007         vert[ 6] = org2[0] - width * right2[0];
7008         vert[ 7] = org2[1] - width * right2[1];
7009         vert[ 8] = org2[2] - width * right2[2];
7010         vert[ 9] = org2[0] + width * right2[0];
7011         vert[10] = org2[1] + width * right2[1];
7012         vert[11] = org2[2] + width * right2[2];
7013 }
7014
7015 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)
7016 {
7017         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7018         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7019         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7020         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7021         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7022         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7023         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7024         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7025         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7026         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7027         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7028         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7029 }
7030
7031 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7032 {
7033         int i;
7034         float *vertex3f;
7035         float v[3];
7036         VectorSet(v, x, y, z);
7037         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7038                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7039                         break;
7040         if (i == mesh->numvertices)
7041         {
7042                 if (mesh->numvertices < mesh->maxvertices)
7043                 {
7044                         VectorCopy(v, vertex3f);
7045                         mesh->numvertices++;
7046                 }
7047                 return mesh->numvertices;
7048         }
7049         else
7050                 return i;
7051 }
7052
7053 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7054 {
7055         int i;
7056         int *e, element[3];
7057         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7058         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7059         e = mesh->element3i + mesh->numtriangles * 3;
7060         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7061         {
7062                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7063                 if (mesh->numtriangles < mesh->maxtriangles)
7064                 {
7065                         *e++ = element[0];
7066                         *e++ = element[1];
7067                         *e++ = element[2];
7068                         mesh->numtriangles++;
7069                 }
7070                 element[1] = element[2];
7071         }
7072 }
7073
7074 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7075 {
7076         int i;
7077         int *e, element[3];
7078         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7079         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7080         e = mesh->element3i + mesh->numtriangles * 3;
7081         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7082         {
7083                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7084                 if (mesh->numtriangles < mesh->maxtriangles)
7085                 {
7086                         *e++ = element[0];
7087                         *e++ = element[1];
7088                         *e++ = element[2];
7089                         mesh->numtriangles++;
7090                 }
7091                 element[1] = element[2];
7092         }
7093 }
7094
7095 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7096 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7097 {
7098         int planenum, planenum2;
7099         int w;
7100         int tempnumpoints;
7101         mplane_t *plane, *plane2;
7102         double maxdist;
7103         double temppoints[2][256*3];
7104         // figure out how large a bounding box we need to properly compute this brush
7105         maxdist = 0;
7106         for (w = 0;w < numplanes;w++)
7107                 maxdist = max(maxdist, fabs(planes[w].dist));
7108         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7109         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7110         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7111         {
7112                 w = 0;
7113                 tempnumpoints = 4;
7114                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7115                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7116                 {
7117                         if (planenum2 == planenum)
7118                                 continue;
7119                         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);
7120                         w = !w;
7121                 }
7122                 if (tempnumpoints < 3)
7123                         continue;
7124                 // generate elements forming a triangle fan for this polygon
7125                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7126         }
7127 }
7128
7129 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)
7130 {
7131         texturelayer_t *layer;
7132         layer = t->currentlayers + t->currentnumlayers++;
7133         layer->type = type;
7134         layer->depthmask = depthmask;
7135         layer->blendfunc1 = blendfunc1;
7136         layer->blendfunc2 = blendfunc2;
7137         layer->texture = texture;
7138         layer->texmatrix = *matrix;
7139         layer->color[0] = r;
7140         layer->color[1] = g;
7141         layer->color[2] = b;
7142         layer->color[3] = a;
7143 }
7144
7145 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7146 {
7147         if(parms[0] == 0 && parms[1] == 0)
7148                 return false;
7149         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7150                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7151                         return false;
7152         return true;
7153 }
7154
7155 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7156 {
7157         double index, f;
7158         index = parms[2] + r_refdef.scene.time * parms[3];
7159         index -= floor(index);
7160         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7161         {
7162         default:
7163         case Q3WAVEFUNC_NONE:
7164         case Q3WAVEFUNC_NOISE:
7165         case Q3WAVEFUNC_COUNT:
7166                 f = 0;
7167                 break;
7168         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7169         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7170         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7171         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7172         case Q3WAVEFUNC_TRIANGLE:
7173                 index *= 4;
7174                 f = index - floor(index);
7175                 if (index < 1)
7176                         f = f;
7177                 else if (index < 2)
7178                         f = 1 - f;
7179                 else if (index < 3)
7180                         f = -f;
7181                 else
7182                         f = -(1 - f);
7183                 break;
7184         }
7185         f = parms[0] + parms[1] * f;
7186         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7187                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7188         return (float) f;
7189 }
7190
7191 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7192 {
7193         int w, h, idx;
7194         float f;
7195         float tcmat[12];
7196         matrix4x4_t matrix, temp;
7197         switch(tcmod->tcmod)
7198         {
7199                 case Q3TCMOD_COUNT:
7200                 case Q3TCMOD_NONE:
7201                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7202                                 matrix = r_waterscrollmatrix;
7203                         else
7204                                 matrix = identitymatrix;
7205                         break;
7206                 case Q3TCMOD_ENTITYTRANSLATE:
7207                         // this is used in Q3 to allow the gamecode to control texcoord
7208                         // scrolling on the entity, which is not supported in darkplaces yet.
7209                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7210                         break;
7211                 case Q3TCMOD_ROTATE:
7212                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7213                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7214                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7215                         break;
7216                 case Q3TCMOD_SCALE:
7217                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7218                         break;
7219                 case Q3TCMOD_SCROLL:
7220                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7221                         break;
7222                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7223                         w = (int) tcmod->parms[0];
7224                         h = (int) tcmod->parms[1];
7225                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7226                         f = f - floor(f);
7227                         idx = (int) floor(f * w * h);
7228                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7229                         break;
7230                 case Q3TCMOD_STRETCH:
7231                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7232                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7233                         break;
7234                 case Q3TCMOD_TRANSFORM:
7235                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7236                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7237                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7238                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7239                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7240                         break;
7241                 case Q3TCMOD_TURBULENT:
7242                         // this is handled in the RSurf_PrepareVertices function
7243                         matrix = identitymatrix;
7244                         break;
7245         }
7246         temp = *texmatrix;
7247         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7248 }
7249
7250 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7251 {
7252         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7253         char name[MAX_QPATH];
7254         skinframe_t *skinframe;
7255         unsigned char pixels[296*194];
7256         strlcpy(cache->name, skinname, sizeof(cache->name));
7257         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7258         if (developer_loading.integer)
7259                 Con_Printf("loading %s\n", name);
7260         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7261         if (!skinframe || !skinframe->base)
7262         {
7263                 unsigned char *f;
7264                 fs_offset_t filesize;
7265                 skinframe = NULL;
7266                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7267                 if (f)
7268                 {
7269                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7270                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7271                         Mem_Free(f);
7272                 }
7273         }
7274         cache->skinframe = skinframe;
7275 }
7276
7277 texture_t *R_GetCurrentTexture(texture_t *t)
7278 {
7279         int i;
7280         const entity_render_t *ent = rsurface.entity;
7281         dp_model_t *model = ent->model;
7282         q3shaderinfo_layer_tcmod_t *tcmod;
7283
7284         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7285                 return t->currentframe;
7286         t->update_lastrenderframe = r_textureframe;
7287         t->update_lastrenderentity = (void *)ent;
7288
7289         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7290                 t->camera_entity = ent->entitynumber;
7291         else
7292                 t->camera_entity = 0;
7293
7294         // switch to an alternate material if this is a q1bsp animated material
7295         {
7296                 texture_t *texture = t;
7297                 int s = rsurface.ent_skinnum;
7298                 if ((unsigned int)s >= (unsigned int)model->numskins)
7299                         s = 0;
7300                 if (model->skinscenes)
7301                 {
7302                         if (model->skinscenes[s].framecount > 1)
7303                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7304                         else
7305                                 s = model->skinscenes[s].firstframe;
7306                 }
7307                 if (s > 0)
7308                         t = t + s * model->num_surfaces;
7309                 if (t->animated)
7310                 {
7311                         // use an alternate animation if the entity's frame is not 0,
7312                         // and only if the texture has an alternate animation
7313                         if (rsurface.ent_alttextures && t->anim_total[1])
7314                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7315                         else
7316                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7317                 }
7318                 texture->currentframe = t;
7319         }
7320
7321         // update currentskinframe to be a qw skin or animation frame
7322         if (rsurface.ent_qwskin >= 0)
7323         {
7324                 i = rsurface.ent_qwskin;
7325                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7326                 {
7327                         r_qwskincache_size = cl.maxclients;
7328                         if (r_qwskincache)
7329                                 Mem_Free(r_qwskincache);
7330                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7331                 }
7332                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7333                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7334                 t->currentskinframe = r_qwskincache[i].skinframe;
7335                 if (t->currentskinframe == NULL)
7336                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7337         }
7338         else if (t->numskinframes >= 2)
7339                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7340         if (t->backgroundnumskinframes >= 2)
7341                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7342
7343         t->currentmaterialflags = t->basematerialflags;
7344         t->currentalpha = rsurface.colormod[3];
7345         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7346                 t->currentalpha *= r_wateralpha.value;
7347         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7348                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7349         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7350                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7351         if (!(rsurface.ent_flags & RENDER_LIGHT))
7352                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7353         else if (FAKELIGHT_ENABLED)
7354         {
7355                         // no modellight if using fakelight for the map
7356         }
7357         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7358         {
7359                 // pick a model lighting mode
7360                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7361                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7362                 else
7363                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7364         }
7365         if (rsurface.ent_flags & RENDER_ADDITIVE)
7366                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7367         else if (t->currentalpha < 1)
7368                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7369         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7370                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7371         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7372                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7373         if (t->backgroundnumskinframes)
7374                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7375         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7376         {
7377                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7378                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7379         }
7380         else
7381                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7382         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7383                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7384
7385         // there is no tcmod
7386         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7387         {
7388                 t->currenttexmatrix = r_waterscrollmatrix;
7389                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7390         }
7391         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7392         {
7393                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7394                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7395         }
7396
7397         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7398                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7399         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7400                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7401
7402         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7403         if (t->currentskinframe->qpixels)
7404                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7405         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7406         if (!t->basetexture)
7407                 t->basetexture = r_texture_notexture;
7408         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7409         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7410         t->nmaptexture = t->currentskinframe->nmap;
7411         if (!t->nmaptexture)
7412                 t->nmaptexture = r_texture_blanknormalmap;
7413         t->glosstexture = r_texture_black;
7414         t->glowtexture = t->currentskinframe->glow;
7415         t->fogtexture = t->currentskinframe->fog;
7416         t->reflectmasktexture = t->currentskinframe->reflect;
7417         if (t->backgroundnumskinframes)
7418         {
7419                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7420                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7421                 t->backgroundglosstexture = r_texture_black;
7422                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7423                 if (!t->backgroundnmaptexture)
7424                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7425         }
7426         else
7427         {
7428                 t->backgroundbasetexture = r_texture_white;
7429                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7430                 t->backgroundglosstexture = r_texture_black;
7431                 t->backgroundglowtexture = NULL;
7432         }
7433         t->specularpower = r_shadow_glossexponent.value;
7434         // TODO: store reference values for these in the texture?
7435         t->specularscale = 0;
7436         if (r_shadow_gloss.integer > 0)
7437         {
7438                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7439                 {
7440                         if (r_shadow_glossintensity.value > 0)
7441                         {
7442                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7443                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7444                                 t->specularscale = r_shadow_glossintensity.value;
7445                         }
7446                 }
7447                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7448                 {
7449                         t->glosstexture = r_texture_white;
7450                         t->backgroundglosstexture = r_texture_white;
7451                         t->specularscale = r_shadow_gloss2intensity.value;
7452                         t->specularpower = r_shadow_gloss2exponent.value;
7453                 }
7454         }
7455         t->specularscale *= t->specularscalemod;
7456         t->specularpower *= t->specularpowermod;
7457
7458         // lightmaps mode looks bad with dlights using actual texturing, so turn
7459         // off the colormap and glossmap, but leave the normalmap on as it still
7460         // accurately represents the shading involved
7461         if (gl_lightmaps.integer)
7462         {
7463                 t->basetexture = r_texture_grey128;
7464                 t->pantstexture = r_texture_black;
7465                 t->shirttexture = r_texture_black;
7466                 t->nmaptexture = r_texture_blanknormalmap;
7467                 t->glosstexture = r_texture_black;
7468                 t->glowtexture = NULL;
7469                 t->fogtexture = NULL;
7470                 t->reflectmasktexture = NULL;
7471                 t->backgroundbasetexture = NULL;
7472                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7473                 t->backgroundglosstexture = r_texture_black;
7474                 t->backgroundglowtexture = NULL;
7475                 t->specularscale = 0;
7476                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7477         }
7478
7479         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7480         VectorClear(t->dlightcolor);
7481         t->currentnumlayers = 0;
7482         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7483         {
7484                 int blendfunc1, blendfunc2;
7485                 qboolean depthmask;
7486                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7487                 {
7488                         blendfunc1 = GL_SRC_ALPHA;
7489                         blendfunc2 = GL_ONE;
7490                 }
7491                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7492                 {
7493                         blendfunc1 = GL_SRC_ALPHA;
7494                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7495                 }
7496                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7497                 {
7498                         blendfunc1 = t->customblendfunc[0];
7499                         blendfunc2 = t->customblendfunc[1];
7500                 }
7501                 else
7502                 {
7503                         blendfunc1 = GL_ONE;
7504                         blendfunc2 = GL_ZERO;
7505                 }
7506                 // don't colormod evilblend textures
7507                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7508                         VectorSet(t->lightmapcolor, 1, 1, 1);
7509                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7510                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7511                 {
7512                         // fullbright is not affected by r_refdef.lightmapintensity
7513                         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]);
7514                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7515                                 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]);
7516                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7517                                 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]);
7518                 }
7519                 else
7520                 {
7521                         vec3_t ambientcolor;
7522                         float colorscale;
7523                         // set the color tint used for lights affecting this surface
7524                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7525                         colorscale = 2;
7526                         // q3bsp has no lightmap updates, so the lightstylevalue that
7527                         // would normally be baked into the lightmap must be
7528                         // applied to the color
7529                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7530                         if (model->type == mod_brushq3)
7531                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7532                         colorscale *= r_refdef.lightmapintensity;
7533                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7534                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7535                         // basic lit geometry
7536                         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]);
7537                         // add pants/shirt if needed
7538                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7539                                 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]);
7540                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7541                                 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]);
7542                         // now add ambient passes if needed
7543                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7544                         {
7545                                 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]);
7546                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7547                                         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]);
7548                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7549                                         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]);
7550                         }
7551                 }
7552                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7553                         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]);
7554                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7555                 {
7556                         // if this is opaque use alpha blend which will darken the earlier
7557                         // passes cheaply.
7558                         //
7559                         // if this is an alpha blended material, all the earlier passes
7560                         // were darkened by fog already, so we only need to add the fog
7561                         // color ontop through the fog mask texture
7562                         //
7563                         // if this is an additive blended material, all the earlier passes
7564                         // were darkened by fog already, and we should not add fog color
7565                         // (because the background was not darkened, there is no fog color
7566                         // that was lost behind it).
7567                         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]);
7568                 }
7569         }
7570
7571         return t->currentframe;
7572 }
7573
7574 rsurfacestate_t rsurface;
7575
7576 void RSurf_ActiveWorldEntity(void)
7577 {
7578         dp_model_t *model = r_refdef.scene.worldmodel;
7579         //if (rsurface.entity == r_refdef.scene.worldentity)
7580         //      return;
7581         rsurface.entity = r_refdef.scene.worldentity;
7582         rsurface.skeleton = NULL;
7583         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7584         rsurface.ent_skinnum = 0;
7585         rsurface.ent_qwskin = -1;
7586         rsurface.ent_shadertime = 0;
7587         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7588         rsurface.matrix = identitymatrix;
7589         rsurface.inversematrix = identitymatrix;
7590         rsurface.matrixscale = 1;
7591         rsurface.inversematrixscale = 1;
7592         R_EntityMatrix(&identitymatrix);
7593         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7594         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7595         rsurface.fograngerecip = r_refdef.fograngerecip;
7596         rsurface.fogheightfade = r_refdef.fogheightfade;
7597         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7598         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7599         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7600         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7601         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7602         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7603         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7604         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7605         rsurface.colormod[3] = 1;
7606         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);
7607         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7608         rsurface.frameblend[0].lerp = 1;
7609         rsurface.ent_alttextures = false;
7610         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7611         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7612         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7613         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7614         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7615         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7616         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7617         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7618         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7619         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7620         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7621         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7622         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7623         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7624         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7625         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7627         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7628         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7629         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7630         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7631         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7632         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7633         rsurface.modelelement3i = model->surfmesh.data_element3i;
7634         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7635         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7636         rsurface.modelelement3s = model->surfmesh.data_element3s;
7637         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7638         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7639         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7640         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7641         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7642         rsurface.modelsurfaces = model->data_surfaces;
7643         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7644         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7645         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7646         rsurface.modelgeneratedvertex = false;
7647         rsurface.batchgeneratedvertex = false;
7648         rsurface.batchfirstvertex = 0;
7649         rsurface.batchnumvertices = 0;
7650         rsurface.batchfirsttriangle = 0;
7651         rsurface.batchnumtriangles = 0;
7652         rsurface.batchvertex3f  = NULL;
7653         rsurface.batchvertex3f_vertexbuffer = NULL;
7654         rsurface.batchvertex3f_bufferoffset = 0;
7655         rsurface.batchsvector3f = NULL;
7656         rsurface.batchsvector3f_vertexbuffer = NULL;
7657         rsurface.batchsvector3f_bufferoffset = 0;
7658         rsurface.batchtvector3f = NULL;
7659         rsurface.batchtvector3f_vertexbuffer = NULL;
7660         rsurface.batchtvector3f_bufferoffset = 0;
7661         rsurface.batchnormal3f  = NULL;
7662         rsurface.batchnormal3f_vertexbuffer = NULL;
7663         rsurface.batchnormal3f_bufferoffset = 0;
7664         rsurface.batchlightmapcolor4f = NULL;
7665         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7666         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7667         rsurface.batchtexcoordtexture2f = NULL;
7668         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7669         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7670         rsurface.batchtexcoordlightmap2f = NULL;
7671         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7672         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7673         rsurface.batchvertexmesh = NULL;
7674         rsurface.batchvertexmeshbuffer = NULL;
7675         rsurface.batchvertex3fbuffer = NULL;
7676         rsurface.batchelement3i = NULL;
7677         rsurface.batchelement3i_indexbuffer = NULL;
7678         rsurface.batchelement3i_bufferoffset = 0;
7679         rsurface.batchelement3s = NULL;
7680         rsurface.batchelement3s_indexbuffer = NULL;
7681         rsurface.batchelement3s_bufferoffset = 0;
7682         rsurface.passcolor4f = NULL;
7683         rsurface.passcolor4f_vertexbuffer = NULL;
7684         rsurface.passcolor4f_bufferoffset = 0;
7685 }
7686
7687 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7688 {
7689         dp_model_t *model = ent->model;
7690         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7691         //      return;
7692         rsurface.entity = (entity_render_t *)ent;
7693         rsurface.skeleton = ent->skeleton;
7694         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7695         rsurface.ent_skinnum = ent->skinnum;
7696         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;
7697         rsurface.ent_shadertime = ent->shadertime;
7698         rsurface.ent_flags = ent->flags;
7699         rsurface.matrix = ent->matrix;
7700         rsurface.inversematrix = ent->inversematrix;
7701         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7702         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7703         R_EntityMatrix(&rsurface.matrix);
7704         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7705         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7706         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7707         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7708         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7709         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7710         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7711         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7712         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7713         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7714         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7715         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7716         rsurface.colormod[3] = ent->alpha;
7717         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7718         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7719         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7720         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7721         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7722         if (ent->model->brush.submodel && !prepass)
7723         {
7724                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7725                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7726         }
7727         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7728         {
7729                 if (ent->animcache_vertex3f)
7730                 {
7731                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7732                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7733                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7734                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7735                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7736                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7737                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7738                 }
7739                 else if (wanttangents)
7740                 {
7741                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7742                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7743                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7744                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7745                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7746                         rsurface.modelvertexmesh = NULL;
7747                         rsurface.modelvertexmeshbuffer = NULL;
7748                         rsurface.modelvertex3fbuffer = NULL;
7749                 }
7750                 else if (wantnormals)
7751                 {
7752                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7753                         rsurface.modelsvector3f = NULL;
7754                         rsurface.modeltvector3f = NULL;
7755                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7756                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7757                         rsurface.modelvertexmesh = NULL;
7758                         rsurface.modelvertexmeshbuffer = NULL;
7759                         rsurface.modelvertex3fbuffer = NULL;
7760                 }
7761                 else
7762                 {
7763                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7764                         rsurface.modelsvector3f = NULL;
7765                         rsurface.modeltvector3f = NULL;
7766                         rsurface.modelnormal3f = NULL;
7767                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7768                         rsurface.modelvertexmesh = NULL;
7769                         rsurface.modelvertexmeshbuffer = NULL;
7770                         rsurface.modelvertex3fbuffer = NULL;
7771                 }
7772                 rsurface.modelvertex3f_vertexbuffer = 0;
7773                 rsurface.modelvertex3f_bufferoffset = 0;
7774                 rsurface.modelsvector3f_vertexbuffer = 0;
7775                 rsurface.modelsvector3f_bufferoffset = 0;
7776                 rsurface.modeltvector3f_vertexbuffer = 0;
7777                 rsurface.modeltvector3f_bufferoffset = 0;
7778                 rsurface.modelnormal3f_vertexbuffer = 0;
7779                 rsurface.modelnormal3f_bufferoffset = 0;
7780                 rsurface.modelgeneratedvertex = true;
7781         }
7782         else
7783         {
7784                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7785                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7787                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7788                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7789                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7790                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7791                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7792                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7793                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7794                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7795                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7796                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7797                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7798                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7799                 rsurface.modelgeneratedvertex = false;
7800         }
7801         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7802         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7803         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7804         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7805         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7806         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7807         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7808         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7809         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7810         rsurface.modelelement3i = model->surfmesh.data_element3i;
7811         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7812         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7813         rsurface.modelelement3s = model->surfmesh.data_element3s;
7814         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7815         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7816         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7817         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7818         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7819         rsurface.modelsurfaces = model->data_surfaces;
7820         rsurface.batchgeneratedvertex = false;
7821         rsurface.batchfirstvertex = 0;
7822         rsurface.batchnumvertices = 0;
7823         rsurface.batchfirsttriangle = 0;
7824         rsurface.batchnumtriangles = 0;
7825         rsurface.batchvertex3f  = NULL;
7826         rsurface.batchvertex3f_vertexbuffer = NULL;
7827         rsurface.batchvertex3f_bufferoffset = 0;
7828         rsurface.batchsvector3f = NULL;
7829         rsurface.batchsvector3f_vertexbuffer = NULL;
7830         rsurface.batchsvector3f_bufferoffset = 0;
7831         rsurface.batchtvector3f = NULL;
7832         rsurface.batchtvector3f_vertexbuffer = NULL;
7833         rsurface.batchtvector3f_bufferoffset = 0;
7834         rsurface.batchnormal3f  = NULL;
7835         rsurface.batchnormal3f_vertexbuffer = NULL;
7836         rsurface.batchnormal3f_bufferoffset = 0;
7837         rsurface.batchlightmapcolor4f = NULL;
7838         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7839         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7840         rsurface.batchtexcoordtexture2f = NULL;
7841         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7842         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7843         rsurface.batchtexcoordlightmap2f = NULL;
7844         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7845         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7846         rsurface.batchvertexmesh = NULL;
7847         rsurface.batchvertexmeshbuffer = NULL;
7848         rsurface.batchvertex3fbuffer = NULL;
7849         rsurface.batchelement3i = NULL;
7850         rsurface.batchelement3i_indexbuffer = NULL;
7851         rsurface.batchelement3i_bufferoffset = 0;
7852         rsurface.batchelement3s = NULL;
7853         rsurface.batchelement3s_indexbuffer = NULL;
7854         rsurface.batchelement3s_bufferoffset = 0;
7855         rsurface.passcolor4f = NULL;
7856         rsurface.passcolor4f_vertexbuffer = NULL;
7857         rsurface.passcolor4f_bufferoffset = 0;
7858 }
7859
7860 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)
7861 {
7862         rsurface.entity = r_refdef.scene.worldentity;
7863         rsurface.skeleton = NULL;
7864         rsurface.ent_skinnum = 0;
7865         rsurface.ent_qwskin = -1;
7866         rsurface.ent_shadertime = shadertime;
7867         rsurface.ent_flags = entflags;
7868         rsurface.modelnumvertices = numvertices;
7869         rsurface.modelnumtriangles = numtriangles;
7870         rsurface.matrix = *matrix;
7871         rsurface.inversematrix = *inversematrix;
7872         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7873         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7874         R_EntityMatrix(&rsurface.matrix);
7875         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7876         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7877         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7878         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7879         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7880         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7881         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7882         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7883         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7884         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7885         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7886         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7887         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);
7888         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7889         rsurface.frameblend[0].lerp = 1;
7890         rsurface.ent_alttextures = false;
7891         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7892         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7893         if (wanttangents)
7894         {
7895                 rsurface.modelvertex3f = (float *)vertex3f;
7896                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7897                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7898                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7899         }
7900         else if (wantnormals)
7901         {
7902                 rsurface.modelvertex3f = (float *)vertex3f;
7903                 rsurface.modelsvector3f = NULL;
7904                 rsurface.modeltvector3f = NULL;
7905                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7906         }
7907         else
7908         {
7909                 rsurface.modelvertex3f = (float *)vertex3f;
7910                 rsurface.modelsvector3f = NULL;
7911                 rsurface.modeltvector3f = NULL;
7912                 rsurface.modelnormal3f = NULL;
7913         }
7914         rsurface.modelvertexmesh = NULL;
7915         rsurface.modelvertexmeshbuffer = NULL;
7916         rsurface.modelvertex3fbuffer = NULL;
7917         rsurface.modelvertex3f_vertexbuffer = 0;
7918         rsurface.modelvertex3f_bufferoffset = 0;
7919         rsurface.modelsvector3f_vertexbuffer = 0;
7920         rsurface.modelsvector3f_bufferoffset = 0;
7921         rsurface.modeltvector3f_vertexbuffer = 0;
7922         rsurface.modeltvector3f_bufferoffset = 0;
7923         rsurface.modelnormal3f_vertexbuffer = 0;
7924         rsurface.modelnormal3f_bufferoffset = 0;
7925         rsurface.modelgeneratedvertex = true;
7926         rsurface.modellightmapcolor4f  = (float *)color4f;
7927         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7928         rsurface.modellightmapcolor4f_bufferoffset = 0;
7929         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7930         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7931         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7932         rsurface.modeltexcoordlightmap2f  = NULL;
7933         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7934         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7935         rsurface.modelelement3i = (int *)element3i;
7936         rsurface.modelelement3i_indexbuffer = NULL;
7937         rsurface.modelelement3i_bufferoffset = 0;
7938         rsurface.modelelement3s = (unsigned short *)element3s;
7939         rsurface.modelelement3s_indexbuffer = NULL;
7940         rsurface.modelelement3s_bufferoffset = 0;
7941         rsurface.modellightmapoffsets = NULL;
7942         rsurface.modelsurfaces = NULL;
7943         rsurface.batchgeneratedvertex = false;
7944         rsurface.batchfirstvertex = 0;
7945         rsurface.batchnumvertices = 0;
7946         rsurface.batchfirsttriangle = 0;
7947         rsurface.batchnumtriangles = 0;
7948         rsurface.batchvertex3f  = NULL;
7949         rsurface.batchvertex3f_vertexbuffer = NULL;
7950         rsurface.batchvertex3f_bufferoffset = 0;
7951         rsurface.batchsvector3f = NULL;
7952         rsurface.batchsvector3f_vertexbuffer = NULL;
7953         rsurface.batchsvector3f_bufferoffset = 0;
7954         rsurface.batchtvector3f = NULL;
7955         rsurface.batchtvector3f_vertexbuffer = NULL;
7956         rsurface.batchtvector3f_bufferoffset = 0;
7957         rsurface.batchnormal3f  = NULL;
7958         rsurface.batchnormal3f_vertexbuffer = NULL;
7959         rsurface.batchnormal3f_bufferoffset = 0;
7960         rsurface.batchlightmapcolor4f = NULL;
7961         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7962         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7963         rsurface.batchtexcoordtexture2f = NULL;
7964         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7965         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7966         rsurface.batchtexcoordlightmap2f = NULL;
7967         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7968         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7969         rsurface.batchvertexmesh = NULL;
7970         rsurface.batchvertexmeshbuffer = NULL;
7971         rsurface.batchvertex3fbuffer = NULL;
7972         rsurface.batchelement3i = NULL;
7973         rsurface.batchelement3i_indexbuffer = NULL;
7974         rsurface.batchelement3i_bufferoffset = 0;
7975         rsurface.batchelement3s = NULL;
7976         rsurface.batchelement3s_indexbuffer = NULL;
7977         rsurface.batchelement3s_bufferoffset = 0;
7978         rsurface.passcolor4f = NULL;
7979         rsurface.passcolor4f_vertexbuffer = NULL;
7980         rsurface.passcolor4f_bufferoffset = 0;
7981
7982         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7983         {
7984                 if ((wantnormals || wanttangents) && !normal3f)
7985                 {
7986                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7987                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7988                 }
7989                 if (wanttangents && !svector3f)
7990                 {
7991                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7992                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7993                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7994                 }
7995         }
7996 }
7997
7998 float RSurf_FogPoint(const float *v)
7999 {
8000         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8001         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8002         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8003         float FogHeightFade = r_refdef.fogheightfade;
8004         float fogfrac;
8005         unsigned int fogmasktableindex;
8006         if (r_refdef.fogplaneviewabove)
8007                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8008         else
8009                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8010         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8011         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8012 }
8013
8014 float RSurf_FogVertex(const float *v)
8015 {
8016         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8017         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8018         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8019         float FogHeightFade = rsurface.fogheightfade;
8020         float fogfrac;
8021         unsigned int fogmasktableindex;
8022         if (r_refdef.fogplaneviewabove)
8023                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8024         else
8025                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8026         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8027         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8028 }
8029
8030 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8031 {
8032         int i;
8033         for (i = 0;i < numelements;i++)
8034                 outelement3i[i] = inelement3i[i] + adjust;
8035 }
8036
8037 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8038 extern cvar_t gl_vbo;
8039 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8040 {
8041         int deformindex;
8042         int firsttriangle;
8043         int numtriangles;
8044         int firstvertex;
8045         int endvertex;
8046         int numvertices;
8047         int surfacefirsttriangle;
8048         int surfacenumtriangles;
8049         int surfacefirstvertex;
8050         int surfaceendvertex;
8051         int surfacenumvertices;
8052         int batchnumvertices;
8053         int batchnumtriangles;
8054         int needsupdate;
8055         int i, j;
8056         qboolean gaps;
8057         qboolean dynamicvertex;
8058         float amplitude;
8059         float animpos;
8060         float scale;
8061         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8062         float waveparms[4];
8063         q3shaderinfo_deform_t *deform;
8064         const msurface_t *surface, *firstsurface;
8065         r_vertexmesh_t *vertexmesh;
8066         if (!texturenumsurfaces)
8067                 return;
8068         // find vertex range of this surface batch
8069         gaps = false;
8070         firstsurface = texturesurfacelist[0];
8071         firsttriangle = firstsurface->num_firsttriangle;
8072         batchnumvertices = 0;
8073         batchnumtriangles = 0;
8074         firstvertex = endvertex = firstsurface->num_firstvertex;
8075         for (i = 0;i < texturenumsurfaces;i++)
8076         {
8077                 surface = texturesurfacelist[i];
8078                 if (surface != firstsurface + i)
8079                         gaps = true;
8080                 surfacefirstvertex = surface->num_firstvertex;
8081                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8082                 surfacenumvertices = surface->num_vertices;
8083                 surfacenumtriangles = surface->num_triangles;
8084                 if (firstvertex > surfacefirstvertex)
8085                         firstvertex = surfacefirstvertex;
8086                 if (endvertex < surfaceendvertex)
8087                         endvertex = surfaceendvertex;
8088                 batchnumvertices += surfacenumvertices;
8089                 batchnumtriangles += surfacenumtriangles;
8090         }
8091
8092         // we now know the vertex range used, and if there are any gaps in it
8093         rsurface.batchfirstvertex = firstvertex;
8094         rsurface.batchnumvertices = endvertex - firstvertex;
8095         rsurface.batchfirsttriangle = firsttriangle;
8096         rsurface.batchnumtriangles = batchnumtriangles;
8097
8098         // this variable holds flags for which properties have been updated that
8099         // may require regenerating vertexmesh array...
8100         needsupdate = 0;
8101
8102         // check if any dynamic vertex processing must occur
8103         dynamicvertex = false;
8104
8105         // if there is a chance of animated vertex colors, it's a dynamic batch
8106         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8107         {
8108                 dynamicvertex = true;
8109                 batchneed |= BATCHNEED_NOGAPS;
8110                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8111         }
8112
8113         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8114         {
8115                 switch (deform->deform)
8116                 {
8117                 default:
8118                 case Q3DEFORM_PROJECTIONSHADOW:
8119                 case Q3DEFORM_TEXT0:
8120                 case Q3DEFORM_TEXT1:
8121                 case Q3DEFORM_TEXT2:
8122                 case Q3DEFORM_TEXT3:
8123                 case Q3DEFORM_TEXT4:
8124                 case Q3DEFORM_TEXT5:
8125                 case Q3DEFORM_TEXT6:
8126                 case Q3DEFORM_TEXT7:
8127                 case Q3DEFORM_NONE:
8128                         break;
8129                 case Q3DEFORM_AUTOSPRITE:
8130                         dynamicvertex = true;
8131                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8132                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8133                         break;
8134                 case Q3DEFORM_AUTOSPRITE2:
8135                         dynamicvertex = true;
8136                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8137                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8138                         break;
8139                 case Q3DEFORM_NORMAL:
8140                         dynamicvertex = true;
8141                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8142                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8143                         break;
8144                 case Q3DEFORM_WAVE:
8145                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8146                                 break; // if wavefunc is a nop, ignore this transform
8147                         dynamicvertex = true;
8148                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8149                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8150                         break;
8151                 case Q3DEFORM_BULGE:
8152                         dynamicvertex = true;
8153                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8154                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8155                         break;
8156                 case Q3DEFORM_MOVE:
8157                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8158                                 break; // if wavefunc is a nop, ignore this transform
8159                         dynamicvertex = true;
8160                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8161                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8162                         break;
8163                 }
8164         }
8165         switch(rsurface.texture->tcgen.tcgen)
8166         {
8167         default:
8168         case Q3TCGEN_TEXTURE:
8169                 break;
8170         case Q3TCGEN_LIGHTMAP:
8171                 dynamicvertex = true;
8172                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8173                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8174                 break;
8175         case Q3TCGEN_VECTOR:
8176                 dynamicvertex = true;
8177                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8178                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8179                 break;
8180         case Q3TCGEN_ENVIRONMENT:
8181                 dynamicvertex = true;
8182                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8183                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8184                 break;
8185         }
8186         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8187         {
8188                 dynamicvertex = true;
8189                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8190                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8191         }
8192
8193         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8194         {
8195                 dynamicvertex = true;
8196                 batchneed |= BATCHNEED_NOGAPS;
8197                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8198         }
8199
8200         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8201         {
8202                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8203                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8204                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8205                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8206                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8207                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8208                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8209         }
8210
8211         // when the model data has no vertex buffer (dynamic mesh), we need to
8212         // eliminate gaps
8213         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8214                 batchneed |= BATCHNEED_NOGAPS;
8215
8216         // if needsupdate, we have to do a dynamic vertex batch for sure
8217         if (needsupdate & batchneed)
8218                 dynamicvertex = true;
8219
8220         // see if we need to build vertexmesh from arrays
8221         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8222                 dynamicvertex = true;
8223
8224         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8225         // also some drivers strongly dislike firstvertex
8226         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8227                 dynamicvertex = true;
8228
8229         rsurface.batchvertex3f = rsurface.modelvertex3f;
8230         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8231         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8232         rsurface.batchsvector3f = rsurface.modelsvector3f;
8233         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8234         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8235         rsurface.batchtvector3f = rsurface.modeltvector3f;
8236         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8237         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8238         rsurface.batchnormal3f = rsurface.modelnormal3f;
8239         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8240         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8241         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8242         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8243         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8244         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8245         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8246         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8247         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8248         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8249         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8250         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8251         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8252         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8253         rsurface.batchelement3i = rsurface.modelelement3i;
8254         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8255         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8256         rsurface.batchelement3s = rsurface.modelelement3s;
8257         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8258         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8259
8260         // if any dynamic vertex processing has to occur in software, we copy the
8261         // entire surface list together before processing to rebase the vertices
8262         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8263         //
8264         // if any gaps exist and we do not have a static vertex buffer, we have to
8265         // copy the surface list together to avoid wasting upload bandwidth on the
8266         // vertices in the gaps.
8267         //
8268         // if gaps exist and we have a static vertex buffer, we still have to
8269         // combine the index buffer ranges into one dynamic index buffer.
8270         //
8271         // in all cases we end up with data that can be drawn in one call.
8272
8273         if (!dynamicvertex)
8274         {
8275                 // static vertex data, just set pointers...
8276                 rsurface.batchgeneratedvertex = false;
8277                 // if there are gaps, we want to build a combined index buffer,
8278                 // otherwise use the original static buffer with an appropriate offset
8279                 if (gaps)
8280                 {
8281                         // build a new triangle elements array for this batch
8282                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8283                         rsurface.batchfirsttriangle = 0;
8284                         numtriangles = 0;
8285                         for (i = 0;i < texturenumsurfaces;i++)
8286                         {
8287                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8288                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8289                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8290                                 numtriangles += surfacenumtriangles;
8291                         }
8292                         rsurface.batchelement3i_indexbuffer = NULL;
8293                         rsurface.batchelement3i_bufferoffset = 0;
8294                         rsurface.batchelement3s = NULL;
8295                         rsurface.batchelement3s_indexbuffer = NULL;
8296                         rsurface.batchelement3s_bufferoffset = 0;
8297                         if (endvertex <= 65536)
8298                         {
8299                                 // make a 16bit (unsigned short) index array if possible
8300                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8301                                 for (i = 0;i < numtriangles*3;i++)
8302                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8303                         }
8304                 }
8305                 return;
8306         }
8307
8308         // something needs software processing, do it for real...
8309         // we only directly handle separate array data in this case and then
8310         // generate interleaved data if needed...
8311         rsurface.batchgeneratedvertex = true;
8312
8313         // now copy the vertex data into a combined array and make an index array
8314         // (this is what Quake3 does all the time)
8315         //if (gaps || rsurface.batchfirstvertex)
8316         {
8317                 rsurface.batchvertex3fbuffer = NULL;
8318                 rsurface.batchvertexmesh = NULL;
8319                 rsurface.batchvertexmeshbuffer = NULL;
8320                 rsurface.batchvertex3f = NULL;
8321                 rsurface.batchvertex3f_vertexbuffer = NULL;
8322                 rsurface.batchvertex3f_bufferoffset = 0;
8323                 rsurface.batchsvector3f = NULL;
8324                 rsurface.batchsvector3f_vertexbuffer = NULL;
8325                 rsurface.batchsvector3f_bufferoffset = 0;
8326                 rsurface.batchtvector3f = NULL;
8327                 rsurface.batchtvector3f_vertexbuffer = NULL;
8328                 rsurface.batchtvector3f_bufferoffset = 0;
8329                 rsurface.batchnormal3f = NULL;
8330                 rsurface.batchnormal3f_vertexbuffer = NULL;
8331                 rsurface.batchnormal3f_bufferoffset = 0;
8332                 rsurface.batchlightmapcolor4f = NULL;
8333                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8334                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8335                 rsurface.batchtexcoordtexture2f = NULL;
8336                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8337                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8338                 rsurface.batchtexcoordlightmap2f = NULL;
8339                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8340                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8341                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8342                 rsurface.batchelement3i_indexbuffer = NULL;
8343                 rsurface.batchelement3i_bufferoffset = 0;
8344                 rsurface.batchelement3s = NULL;
8345                 rsurface.batchelement3s_indexbuffer = NULL;
8346                 rsurface.batchelement3s_bufferoffset = 0;
8347                 // we'll only be setting up certain arrays as needed
8348                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8349                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8350                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8351                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8352                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8353                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8354                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8355                 {
8356                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8357                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8358                 }
8359                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8360                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8361                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8362                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8363                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8364                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8365                 numvertices = 0;
8366                 numtriangles = 0;
8367                 for (i = 0;i < texturenumsurfaces;i++)
8368                 {
8369                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8370                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8371                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8372                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8373                         // copy only the data requested
8374                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8375                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8376                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8377                         {
8378                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8379                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8380                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8381                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8382                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8383                                 {
8384                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8385                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8386                                 }
8387                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8388                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8389                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8390                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8391                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8392                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8393                         }
8394                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8395                         numvertices += surfacenumvertices;
8396                         numtriangles += surfacenumtriangles;
8397                 }
8398
8399                 // generate a 16bit index array as well if possible
8400                 // (in general, dynamic batches fit)
8401                 if (numvertices <= 65536)
8402                 {
8403                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8404                         for (i = 0;i < numtriangles*3;i++)
8405                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8406                 }
8407
8408                 // since we've copied everything, the batch now starts at 0
8409                 rsurface.batchfirstvertex = 0;
8410                 rsurface.batchnumvertices = batchnumvertices;
8411                 rsurface.batchfirsttriangle = 0;
8412                 rsurface.batchnumtriangles = batchnumtriangles;
8413         }
8414
8415         // q1bsp surfaces rendered in vertex color mode have to have colors
8416         // calculated based on lightstyles
8417         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8418         {
8419                 // generate color arrays for the surfaces in this list
8420                 int c[4];
8421                 int scale;
8422                 int size3;
8423                 const int *offsets;
8424                 const unsigned char *lm;
8425                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8426                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8427                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8428                 numvertices = 0;
8429                 for (i = 0;i < texturenumsurfaces;i++)
8430                 {
8431                         surface = texturesurfacelist[i];
8432                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8433                         surfacenumvertices = surface->num_vertices;
8434                         if (surface->lightmapinfo->samples)
8435                         {
8436                                 for (j = 0;j < surfacenumvertices;j++)
8437                                 {
8438                                         lm = surface->lightmapinfo->samples + offsets[j];
8439                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8440                                         VectorScale(lm, scale, c);
8441                                         if (surface->lightmapinfo->styles[1] != 255)
8442                                         {
8443                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8444                                                 lm += size3;
8445                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8446                                                 VectorMA(c, scale, lm, c);
8447                                                 if (surface->lightmapinfo->styles[2] != 255)
8448                                                 {
8449                                                         lm += size3;
8450                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8451                                                         VectorMA(c, scale, lm, c);
8452                                                         if (surface->lightmapinfo->styles[3] != 255)
8453                                                         {
8454                                                                 lm += size3;
8455                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8456                                                                 VectorMA(c, scale, lm, c);
8457                                                         }
8458                                                 }
8459                                         }
8460                                         c[0] >>= 7;
8461                                         c[1] >>= 7;
8462                                         c[2] >>= 7;
8463                                         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);
8464                                         numvertices++;
8465                                 }
8466                         }
8467                         else
8468                         {
8469                                 for (j = 0;j < surfacenumvertices;j++)
8470                                 {
8471                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8472                                         numvertices++;
8473                                 }
8474                         }
8475                 }
8476         }
8477
8478         // if vertices are deformed (sprite flares and things in maps, possibly
8479         // water waves, bulges and other deformations), modify the copied vertices
8480         // in place
8481         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8482         {
8483                 switch (deform->deform)
8484                 {
8485                 default:
8486                 case Q3DEFORM_PROJECTIONSHADOW:
8487                 case Q3DEFORM_TEXT0:
8488                 case Q3DEFORM_TEXT1:
8489                 case Q3DEFORM_TEXT2:
8490                 case Q3DEFORM_TEXT3:
8491                 case Q3DEFORM_TEXT4:
8492                 case Q3DEFORM_TEXT5:
8493                 case Q3DEFORM_TEXT6:
8494                 case Q3DEFORM_TEXT7:
8495                 case Q3DEFORM_NONE:
8496                         break;
8497                 case Q3DEFORM_AUTOSPRITE:
8498                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8499                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8500                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8501                         VectorNormalize(newforward);
8502                         VectorNormalize(newright);
8503                         VectorNormalize(newup);
8504 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8505 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8506 //                      rsurface.batchvertex3f_bufferoffset = 0;
8507 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8508 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8509 //                      rsurface.batchsvector3f_bufferoffset = 0;
8510 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8511 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8512 //                      rsurface.batchtvector3f_bufferoffset = 0;
8513 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8514 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8515 //                      rsurface.batchnormal3f_bufferoffset = 0;
8516                         // a single autosprite surface can contain multiple sprites...
8517                         for (j = 0;j < batchnumvertices - 3;j += 4)
8518                         {
8519                                 VectorClear(center);
8520                                 for (i = 0;i < 4;i++)
8521                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8522                                 VectorScale(center, 0.25f, center);
8523                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8524                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8525                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8526                                 for (i = 0;i < 4;i++)
8527                                 {
8528                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8529                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8530                                 }
8531                         }
8532                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8533                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8534                         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);
8535                         break;
8536                 case Q3DEFORM_AUTOSPRITE2:
8537                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8538                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8539                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8540                         VectorNormalize(newforward);
8541                         VectorNormalize(newright);
8542                         VectorNormalize(newup);
8543 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8544 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8545 //                      rsurface.batchvertex3f_bufferoffset = 0;
8546                         {
8547                                 const float *v1, *v2;
8548                                 vec3_t start, end;
8549                                 float f, l;
8550                                 struct
8551                                 {
8552                                         float length2;
8553                                         const float *v1;
8554                                         const float *v2;
8555                                 }
8556                                 shortest[2];
8557                                 memset(shortest, 0, sizeof(shortest));
8558                                 // a single autosprite surface can contain multiple sprites...
8559                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8560                                 {
8561                                         VectorClear(center);
8562                                         for (i = 0;i < 4;i++)
8563                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8564                                         VectorScale(center, 0.25f, center);
8565                                         // find the two shortest edges, then use them to define the
8566                                         // axis vectors for rotating around the central axis
8567                                         for (i = 0;i < 6;i++)
8568                                         {
8569                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8570                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8571                                                 l = VectorDistance2(v1, v2);
8572                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8573                                                 if (v1[2] != v2[2])
8574                                                         l += (1.0f / 1024.0f);
8575                                                 if (shortest[0].length2 > l || i == 0)
8576                                                 {
8577                                                         shortest[1] = shortest[0];
8578                                                         shortest[0].length2 = l;
8579                                                         shortest[0].v1 = v1;
8580                                                         shortest[0].v2 = v2;
8581                                                 }
8582                                                 else if (shortest[1].length2 > l || i == 1)
8583                                                 {
8584                                                         shortest[1].length2 = l;
8585                                                         shortest[1].v1 = v1;
8586                                                         shortest[1].v2 = v2;
8587                                                 }
8588                                         }
8589                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8590                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8591                                         // this calculates the right vector from the shortest edge
8592                                         // and the up vector from the edge midpoints
8593                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8594                                         VectorNormalize(right);
8595                                         VectorSubtract(end, start, up);
8596                                         VectorNormalize(up);
8597                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8598                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8599                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8600                                         VectorNegate(forward, forward);
8601                                         VectorReflect(forward, 0, up, forward);
8602                                         VectorNormalize(forward);
8603                                         CrossProduct(up, forward, newright);
8604                                         VectorNormalize(newright);
8605                                         // rotate the quad around the up axis vector, this is made
8606                                         // especially easy by the fact we know the quad is flat,
8607                                         // so we only have to subtract the center position and
8608                                         // measure distance along the right vector, and then
8609                                         // multiply that by the newright vector and add back the
8610                                         // center position
8611                                         // we also need to subtract the old position to undo the
8612                                         // displacement from the center, which we do with a
8613                                         // DotProduct, the subtraction/addition of center is also
8614                                         // optimized into DotProducts here
8615                                         l = DotProduct(right, center);
8616                                         for (i = 0;i < 4;i++)
8617                                         {
8618                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8619                                                 f = DotProduct(right, v1) - l;
8620                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8621                                         }
8622                                 }
8623                         }
8624                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8625                         {
8626 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8627 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8628 //                              rsurface.batchnormal3f_bufferoffset = 0;
8629                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8630                         }
8631                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8632                         {
8633 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8634 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8635 //                              rsurface.batchsvector3f_bufferoffset = 0;
8636 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8637 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8638 //                              rsurface.batchtvector3f_bufferoffset = 0;
8639                                 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);
8640                         }
8641                         break;
8642                 case Q3DEFORM_NORMAL:
8643                         // deform the normals to make reflections wavey
8644                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8645                         rsurface.batchnormal3f_vertexbuffer = NULL;
8646                         rsurface.batchnormal3f_bufferoffset = 0;
8647                         for (j = 0;j < batchnumvertices;j++)
8648                         {
8649                                 float vertex[3];
8650                                 float *normal = rsurface.batchnormal3f + 3*j;
8651                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8652                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8653                                 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]);
8654                                 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]);
8655                                 VectorNormalize(normal);
8656                         }
8657                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8658                         {
8659 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8660 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8661 //                              rsurface.batchsvector3f_bufferoffset = 0;
8662 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8663 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8664 //                              rsurface.batchtvector3f_bufferoffset = 0;
8665                                 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);
8666                         }
8667                         break;
8668                 case Q3DEFORM_WAVE:
8669                         // deform vertex array to make wavey water and flags and such
8670                         waveparms[0] = deform->waveparms[0];
8671                         waveparms[1] = deform->waveparms[1];
8672                         waveparms[2] = deform->waveparms[2];
8673                         waveparms[3] = deform->waveparms[3];
8674                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8675                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8676                         // this is how a divisor of vertex influence on deformation
8677                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8678                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8679 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8680 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8681 //                      rsurface.batchvertex3f_bufferoffset = 0;
8682 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8683 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8684 //                      rsurface.batchnormal3f_bufferoffset = 0;
8685                         for (j = 0;j < batchnumvertices;j++)
8686                         {
8687                                 // if the wavefunc depends on time, evaluate it per-vertex
8688                                 if (waveparms[3])
8689                                 {
8690                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8691                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8692                                 }
8693                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8694                         }
8695                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8696                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8697                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8698                         {
8699 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8700 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8701 //                              rsurface.batchsvector3f_bufferoffset = 0;
8702 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8703 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8704 //                              rsurface.batchtvector3f_bufferoffset = 0;
8705                                 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);
8706                         }
8707                         break;
8708                 case Q3DEFORM_BULGE:
8709                         // deform vertex array to make the surface have moving bulges
8710 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8711 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8712 //                      rsurface.batchvertex3f_bufferoffset = 0;
8713 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8714 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8715 //                      rsurface.batchnormal3f_bufferoffset = 0;
8716                         for (j = 0;j < batchnumvertices;j++)
8717                         {
8718                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8719                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8720                         }
8721                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8722                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8723                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8724                         {
8725 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8726 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8727 //                              rsurface.batchsvector3f_bufferoffset = 0;
8728 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8729 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8730 //                              rsurface.batchtvector3f_bufferoffset = 0;
8731                                 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);
8732                         }
8733                         break;
8734                 case Q3DEFORM_MOVE:
8735                         // deform vertex array
8736                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8737                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8738                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8739                         VectorScale(deform->parms, scale, waveparms);
8740 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8741 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8742 //                      rsurface.batchvertex3f_bufferoffset = 0;
8743                         for (j = 0;j < batchnumvertices;j++)
8744                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8745                         break;
8746                 }
8747         }
8748
8749         // generate texcoords based on the chosen texcoord source
8750         switch(rsurface.texture->tcgen.tcgen)
8751         {
8752         default:
8753         case Q3TCGEN_TEXTURE:
8754                 break;
8755         case Q3TCGEN_LIGHTMAP:
8756 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8757 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8758 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8759                 if (rsurface.batchtexcoordlightmap2f)
8760                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8761                 break;
8762         case Q3TCGEN_VECTOR:
8763 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8764 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8765 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8766                 for (j = 0;j < batchnumvertices;j++)
8767                 {
8768                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8769                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8770                 }
8771                 break;
8772         case Q3TCGEN_ENVIRONMENT:
8773                 // make environment reflections using a spheremap
8774                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8775                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8776                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8777                 for (j = 0;j < batchnumvertices;j++)
8778                 {
8779                         // identical to Q3A's method, but executed in worldspace so
8780                         // carried models can be shiny too
8781
8782                         float viewer[3], d, reflected[3], worldreflected[3];
8783
8784                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8785                         // VectorNormalize(viewer);
8786
8787                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8788
8789                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8790                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8791                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8792                         // note: this is proportinal to viewer, so we can normalize later
8793
8794                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8795                         VectorNormalize(worldreflected);
8796
8797                         // note: this sphere map only uses world x and z!
8798                         // so positive and negative y will LOOK THE SAME.
8799                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8800                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8801                 }
8802                 break;
8803         }
8804         // the only tcmod that needs software vertex processing is turbulent, so
8805         // check for it here and apply the changes if needed
8806         // and we only support that as the first one
8807         // (handling a mixture of turbulent and other tcmods would be problematic
8808         //  without punting it entirely to a software path)
8809         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8810         {
8811                 amplitude = rsurface.texture->tcmods[0].parms[1];
8812                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8813 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8814 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8815 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8816                 for (j = 0;j < batchnumvertices;j++)
8817                 {
8818                         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);
8819                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8820                 }
8821         }
8822
8823         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8824         {
8825                 // convert the modified arrays to vertex structs
8826 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8827 //              rsurface.batchvertexmeshbuffer = NULL;
8828                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8829                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8830                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8831                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8832                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8833                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8834                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8835                 {
8836                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8837                         {
8838                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8839                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8840                         }
8841                 }
8842                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8843                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8844                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8845                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8846                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8847                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8848                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8849                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8850                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8851         }
8852 }
8853
8854 void RSurf_DrawBatch(void)
8855 {
8856         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8857         // through the pipeline, killing it earlier in the pipeline would have
8858         // per-surface overhead rather than per-batch overhead, so it's best to
8859         // reject it here, before it hits glDraw.
8860         if (rsurface.batchnumtriangles == 0)
8861                 return;
8862 #if 0
8863         // batch debugging code
8864         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8865         {
8866                 int i;
8867                 int j;
8868                 int c;
8869                 const int *e;
8870                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8871                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8872                 {
8873                         c = e[i];
8874                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8875                         {
8876                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8877                                 {
8878                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8879                                                 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);
8880                                         break;
8881                                 }
8882                         }
8883                 }
8884         }
8885 #endif
8886         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);
8887 }
8888
8889 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8890 {
8891         // pick the closest matching water plane
8892         int planeindex, vertexindex, bestplaneindex = -1;
8893         float d, bestd;
8894         vec3_t vert;
8895         const float *v;
8896         r_waterstate_waterplane_t *p;
8897         qboolean prepared = false;
8898         bestd = 0;
8899         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8900         {
8901                 if(p->camera_entity != rsurface.texture->camera_entity)
8902                         continue;
8903                 d = 0;
8904                 if(!prepared)
8905                 {
8906                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8907                         prepared = true;
8908                         if(rsurface.batchnumvertices == 0)
8909                                 break;
8910                 }
8911                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8912                 {
8913                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8914                         d += fabs(PlaneDiff(vert, &p->plane));
8915                 }
8916                 if (bestd > d || bestplaneindex < 0)
8917                 {
8918                         bestd = d;
8919                         bestplaneindex = planeindex;
8920                 }
8921         }
8922         return bestplaneindex;
8923         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8924         // this situation though, as it might be better to render single larger
8925         // batches with useless stuff (backface culled for example) than to
8926         // render multiple smaller batches
8927 }
8928
8929 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8930 {
8931         int i;
8932         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8933         rsurface.passcolor4f_vertexbuffer = 0;
8934         rsurface.passcolor4f_bufferoffset = 0;
8935         for (i = 0;i < rsurface.batchnumvertices;i++)
8936                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8937 }
8938
8939 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8940 {
8941         int i;
8942         float f;
8943         const float *v;
8944         const float *c;
8945         float *c2;
8946         if (rsurface.passcolor4f)
8947         {
8948                 // generate color arrays
8949                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8950                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8951                 rsurface.passcolor4f_vertexbuffer = 0;
8952                 rsurface.passcolor4f_bufferoffset = 0;
8953                 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)
8954                 {
8955                         f = RSurf_FogVertex(v);
8956                         c2[0] = c[0] * f;
8957                         c2[1] = c[1] * f;
8958                         c2[2] = c[2] * f;
8959                         c2[3] = c[3];
8960                 }
8961         }
8962         else
8963         {
8964                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8965                 rsurface.passcolor4f_vertexbuffer = 0;
8966                 rsurface.passcolor4f_bufferoffset = 0;
8967                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8968                 {
8969                         f = RSurf_FogVertex(v);
8970                         c2[0] = f;
8971                         c2[1] = f;
8972                         c2[2] = f;
8973                         c2[3] = 1;
8974                 }
8975         }
8976 }
8977
8978 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8979 {
8980         int i;
8981         float f;
8982         const float *v;
8983         const float *c;
8984         float *c2;
8985         if (!rsurface.passcolor4f)
8986                 return;
8987         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8988         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8989         rsurface.passcolor4f_vertexbuffer = 0;
8990         rsurface.passcolor4f_bufferoffset = 0;
8991         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)
8992         {
8993                 f = RSurf_FogVertex(v);
8994                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8995                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8996                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8997                 c2[3] = c[3];
8998         }
8999 }
9000
9001 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9002 {
9003         int i;
9004         const float *c;
9005         float *c2;
9006         if (!rsurface.passcolor4f)
9007                 return;
9008         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9009         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9010         rsurface.passcolor4f_vertexbuffer = 0;
9011         rsurface.passcolor4f_bufferoffset = 0;
9012         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9013         {
9014                 c2[0] = c[0] * r;
9015                 c2[1] = c[1] * g;
9016                 c2[2] = c[2] * b;
9017                 c2[3] = c[3] * a;
9018         }
9019 }
9020
9021 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9022 {
9023         int i;
9024         const float *c;
9025         float *c2;
9026         if (!rsurface.passcolor4f)
9027                 return;
9028         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9029         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9030         rsurface.passcolor4f_vertexbuffer = 0;
9031         rsurface.passcolor4f_bufferoffset = 0;
9032         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9033         {
9034                 c2[0] = c[0] + r_refdef.scene.ambient;
9035                 c2[1] = c[1] + r_refdef.scene.ambient;
9036                 c2[2] = c[2] + r_refdef.scene.ambient;
9037                 c2[3] = c[3];
9038         }
9039 }
9040
9041 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9042 {
9043         // TODO: optimize
9044         rsurface.passcolor4f = NULL;
9045         rsurface.passcolor4f_vertexbuffer = 0;
9046         rsurface.passcolor4f_bufferoffset = 0;
9047         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9048         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9049         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9050         GL_Color(r, g, b, a);
9051         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9052         RSurf_DrawBatch();
9053 }
9054
9055 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9056 {
9057         // TODO: optimize applyfog && applycolor case
9058         // just apply fog if necessary, and tint the fog color array if necessary
9059         rsurface.passcolor4f = NULL;
9060         rsurface.passcolor4f_vertexbuffer = 0;
9061         rsurface.passcolor4f_bufferoffset = 0;
9062         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9063         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9064         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9065         GL_Color(r, g, b, a);
9066         RSurf_DrawBatch();
9067 }
9068
9069 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9070 {
9071         // TODO: optimize
9072         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9073         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9074         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9075         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9076         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9077         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9078         GL_Color(r, g, b, a);
9079         RSurf_DrawBatch();
9080 }
9081
9082 static void RSurf_DrawBatch_GL11_ClampColor(void)
9083 {
9084         int i;
9085         const float *c1;
9086         float *c2;
9087         if (!rsurface.passcolor4f)
9088                 return;
9089         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9090         {
9091                 c2[0] = bound(0.0f, c1[0], 1.0f);
9092                 c2[1] = bound(0.0f, c1[1], 1.0f);
9093                 c2[2] = bound(0.0f, c1[2], 1.0f);
9094                 c2[3] = bound(0.0f, c1[3], 1.0f);
9095         }
9096 }
9097
9098 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9099 {
9100         int i;
9101         float f;
9102         const float *v;
9103         const float *n;
9104         float *c;
9105         //vec3_t eyedir;
9106
9107         // fake shading
9108         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9109         rsurface.passcolor4f_vertexbuffer = 0;
9110         rsurface.passcolor4f_bufferoffset = 0;
9111         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)
9112         {
9113                 f = -DotProduct(r_refdef.view.forward, n);
9114                 f = max(0, f);
9115                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9116                 f *= r_refdef.lightmapintensity;
9117                 Vector4Set(c, f, f, f, 1);
9118         }
9119 }
9120
9121 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9122 {
9123         RSurf_DrawBatch_GL11_ApplyFakeLight();
9124         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9125         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9126         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9127         GL_Color(r, g, b, a);
9128         RSurf_DrawBatch();
9129 }
9130
9131 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9132 {
9133         int i;
9134         float f;
9135         float alpha;
9136         const float *v;
9137         const float *n;
9138         float *c;
9139         vec3_t ambientcolor;
9140         vec3_t diffusecolor;
9141         vec3_t lightdir;
9142         // TODO: optimize
9143         // model lighting
9144         VectorCopy(rsurface.modellight_lightdir, lightdir);
9145         f = 0.5f * r_refdef.lightmapintensity;
9146         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9147         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9148         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9149         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9150         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9151         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9152         alpha = *a;
9153         if (VectorLength2(diffusecolor) > 0)
9154         {
9155                 // q3-style directional shading
9156                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9157                 rsurface.passcolor4f_vertexbuffer = 0;
9158                 rsurface.passcolor4f_bufferoffset = 0;
9159                 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)
9160                 {
9161                         if ((f = DotProduct(n, lightdir)) > 0)
9162                                 VectorMA(ambientcolor, f, diffusecolor, c);
9163                         else
9164                                 VectorCopy(ambientcolor, c);
9165                         c[3] = alpha;
9166                 }
9167                 *r = 1;
9168                 *g = 1;
9169                 *b = 1;
9170                 *a = 1;
9171                 *applycolor = false;
9172         }
9173         else
9174         {
9175                 *r = ambientcolor[0];
9176                 *g = ambientcolor[1];
9177                 *b = ambientcolor[2];
9178                 rsurface.passcolor4f = NULL;
9179                 rsurface.passcolor4f_vertexbuffer = 0;
9180                 rsurface.passcolor4f_bufferoffset = 0;
9181         }
9182 }
9183
9184 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9185 {
9186         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9187         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9188         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9189         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9190         GL_Color(r, g, b, a);
9191         RSurf_DrawBatch();
9192 }
9193
9194 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9195 {
9196         int i;
9197         float f;
9198         const float *v;
9199         float *c;
9200         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9201         {
9202                 f = 1 - RSurf_FogVertex(v);
9203                 c[0] = r;
9204                 c[1] = g;
9205                 c[2] = b;
9206                 c[3] = f * a;
9207         }
9208 }
9209
9210 void RSurf_SetupDepthAndCulling(void)
9211 {
9212         // submodels are biased to avoid z-fighting with world surfaces that they
9213         // may be exactly overlapping (avoids z-fighting artifacts on certain
9214         // doors and things in Quake maps)
9215         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9216         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9217         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9218         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9219 }
9220
9221 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9222 {
9223         // transparent sky would be ridiculous
9224         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9225                 return;
9226         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9227         skyrenderlater = true;
9228         RSurf_SetupDepthAndCulling();
9229         GL_DepthMask(true);
9230         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9231         // skymasking on them, and Quake3 never did sky masking (unlike
9232         // software Quake and software Quake2), so disable the sky masking
9233         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9234         // and skymasking also looks very bad when noclipping outside the
9235         // level, so don't use it then either.
9236         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9237         {
9238                 R_Mesh_ResetTextureState();
9239                 if (skyrendermasked)
9240                 {
9241                         R_SetupShader_DepthOrShadow();
9242                         // depth-only (masking)
9243                         GL_ColorMask(0,0,0,0);
9244                         // just to make sure that braindead drivers don't draw
9245                         // anything despite that colormask...
9246                         GL_BlendFunc(GL_ZERO, GL_ONE);
9247                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9248                         if (rsurface.batchvertex3fbuffer)
9249                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9250                         else
9251                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9252                 }
9253                 else
9254                 {
9255                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9256                         // fog sky
9257                         GL_BlendFunc(GL_ONE, GL_ZERO);
9258                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9259                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9260                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9261                 }
9262                 RSurf_DrawBatch();
9263                 if (skyrendermasked)
9264                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9265         }
9266         R_Mesh_ResetTextureState();
9267         GL_Color(1, 1, 1, 1);
9268 }
9269
9270 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9271 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9272 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9273 {
9274         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9275                 return;
9276         if (prepass)
9277         {
9278                 // render screenspace normalmap to texture
9279                 GL_DepthMask(true);
9280                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9281                 RSurf_DrawBatch();
9282                 return;
9283         }
9284
9285         // bind lightmap texture
9286
9287         // water/refraction/reflection/camera surfaces have to be handled specially
9288         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9289         {
9290                 int start, end, startplaneindex;
9291                 for (start = 0;start < texturenumsurfaces;start = end)
9292                 {
9293                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9294                         if(startplaneindex < 0)
9295                         {
9296                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9297                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9298                                 end = start + 1;
9299                                 continue;
9300                         }
9301                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9302                                 ;
9303                         // now that we have a batch using the same planeindex, render it
9304                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9305                         {
9306                                 // render water or distortion background
9307                                 GL_DepthMask(true);
9308                                 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));
9309                                 RSurf_DrawBatch();
9310                                 // blend surface on top
9311                                 GL_DepthMask(false);
9312                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9313                                 RSurf_DrawBatch();
9314                         }
9315                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9316                         {
9317                                 // render surface with reflection texture as input
9318                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9319                                 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));
9320                                 RSurf_DrawBatch();
9321                         }
9322                 }
9323                 return;
9324         }
9325
9326         // render surface batch normally
9327         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9328         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9329         RSurf_DrawBatch();
9330 }
9331
9332 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9333 {
9334         // OpenGL 1.3 path - anything not completely ancient
9335         qboolean applycolor;
9336         qboolean applyfog;
9337         int layerindex;
9338         const texturelayer_t *layer;
9339         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);
9340         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9341
9342         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9343         {
9344                 vec4_t layercolor;
9345                 int layertexrgbscale;
9346                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9347                 {
9348                         if (layerindex == 0)
9349                                 GL_AlphaTest(true);
9350                         else
9351                         {
9352                                 GL_AlphaTest(false);
9353                                 GL_DepthFunc(GL_EQUAL);
9354                         }
9355                 }
9356                 GL_DepthMask(layer->depthmask && writedepth);
9357                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9358                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9359                 {
9360                         layertexrgbscale = 4;
9361                         VectorScale(layer->color, 0.25f, layercolor);
9362                 }
9363                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9364                 {
9365                         layertexrgbscale = 2;
9366                         VectorScale(layer->color, 0.5f, layercolor);
9367                 }
9368                 else
9369                 {
9370                         layertexrgbscale = 1;
9371                         VectorScale(layer->color, 1.0f, layercolor);
9372                 }
9373                 layercolor[3] = layer->color[3];
9374                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9375                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9376                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9377                 switch (layer->type)
9378                 {
9379                 case TEXTURELAYERTYPE_LITTEXTURE:
9380                         // single-pass lightmapped texture with 2x rgbscale
9381                         R_Mesh_TexBind(0, r_texture_white);
9382                         R_Mesh_TexMatrix(0, NULL);
9383                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9384                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9385                         R_Mesh_TexBind(1, layer->texture);
9386                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9387                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9388                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9389                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9390                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9391                         else if (FAKELIGHT_ENABLED)
9392                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9393                         else if (rsurface.uselightmaptexture)
9394                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9395                         else
9396                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9397                         break;
9398                 case TEXTURELAYERTYPE_TEXTURE:
9399                         // singletexture unlit texture with transparency support
9400                         R_Mesh_TexBind(0, layer->texture);
9401                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9402                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9403                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9404                         R_Mesh_TexBind(1, 0);
9405                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9406                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9407                         break;
9408                 case TEXTURELAYERTYPE_FOG:
9409                         // singletexture fogging
9410                         if (layer->texture)
9411                         {
9412                                 R_Mesh_TexBind(0, layer->texture);
9413                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9414                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9415                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9416                         }
9417                         else
9418                         {
9419                                 R_Mesh_TexBind(0, 0);
9420                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9421                         }
9422                         R_Mesh_TexBind(1, 0);
9423                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9424                         // generate a color array for the fog pass
9425                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9426                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9427                         RSurf_DrawBatch();
9428                         break;
9429                 default:
9430                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9431                 }
9432         }
9433         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9434         {
9435                 GL_DepthFunc(GL_LEQUAL);
9436                 GL_AlphaTest(false);
9437         }
9438 }
9439
9440 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9441 {
9442         // OpenGL 1.1 - crusty old voodoo path
9443         qboolean applyfog;
9444         int layerindex;
9445         const texturelayer_t *layer;
9446         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);
9447         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9448
9449         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9450         {
9451                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9452                 {
9453                         if (layerindex == 0)
9454                                 GL_AlphaTest(true);
9455                         else
9456                         {
9457                                 GL_AlphaTest(false);
9458                                 GL_DepthFunc(GL_EQUAL);
9459                         }
9460                 }
9461                 GL_DepthMask(layer->depthmask && writedepth);
9462                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9463                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9464                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9465                 switch (layer->type)
9466                 {
9467                 case TEXTURELAYERTYPE_LITTEXTURE:
9468                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9469                         {
9470                                 // two-pass lit texture with 2x rgbscale
9471                                 // first the lightmap pass
9472                                 R_Mesh_TexBind(0, r_texture_white);
9473                                 R_Mesh_TexMatrix(0, NULL);
9474                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9475                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9476                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9477                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9478                                 else if (FAKELIGHT_ENABLED)
9479                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9480                                 else if (rsurface.uselightmaptexture)
9481                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9482                                 else
9483                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9484                                 // then apply the texture to it
9485                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9486                                 R_Mesh_TexBind(0, layer->texture);
9487                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9488                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9489                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9490                                 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);
9491                         }
9492                         else
9493                         {
9494                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9495                                 R_Mesh_TexBind(0, layer->texture);
9496                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9497                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9498                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9499                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9500                                         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);
9501                                 else
9502                                         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);
9503                         }
9504                         break;
9505                 case TEXTURELAYERTYPE_TEXTURE:
9506                         // singletexture unlit texture with transparency support
9507                         R_Mesh_TexBind(0, layer->texture);
9508                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9509                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9510                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9511                         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);
9512                         break;
9513                 case TEXTURELAYERTYPE_FOG:
9514                         // singletexture fogging
9515                         if (layer->texture)
9516                         {
9517                                 R_Mesh_TexBind(0, layer->texture);
9518                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9519                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9520                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9521                         }
9522                         else
9523                         {
9524                                 R_Mesh_TexBind(0, 0);
9525                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9526                         }
9527                         // generate a color array for the fog pass
9528                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9529                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9530                         RSurf_DrawBatch();
9531                         break;
9532                 default:
9533                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9534                 }
9535         }
9536         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9537         {
9538                 GL_DepthFunc(GL_LEQUAL);
9539                 GL_AlphaTest(false);
9540         }
9541 }
9542
9543 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9544 {
9545         int vi;
9546         int j;
9547         r_vertexgeneric_t *batchvertex;
9548         float c[4];
9549
9550 //      R_Mesh_ResetTextureState();
9551         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9552
9553         if(rsurface.texture && rsurface.texture->currentskinframe)
9554         {
9555                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9556                 c[3] *= rsurface.texture->currentalpha;
9557         }
9558         else
9559         {
9560                 c[0] = 1;
9561                 c[1] = 0;
9562                 c[2] = 1;
9563                 c[3] = 1;
9564         }
9565
9566         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9567         {
9568                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9569                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9570                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9571         }
9572
9573         // brighten it up (as texture value 127 means "unlit")
9574         c[0] *= 2 * r_refdef.view.colorscale;
9575         c[1] *= 2 * r_refdef.view.colorscale;
9576         c[2] *= 2 * r_refdef.view.colorscale;
9577
9578         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9579                 c[3] *= r_wateralpha.value;
9580
9581         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9582         {
9583                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9584                 GL_DepthMask(false);
9585         }
9586         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9587         {
9588                 GL_BlendFunc(GL_ONE, GL_ONE);
9589                 GL_DepthMask(false);
9590         }
9591         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9592         {
9593                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9594                 GL_DepthMask(false);
9595         }
9596         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9597         {
9598                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9599                 GL_DepthMask(false);
9600         }
9601         else
9602         {
9603                 GL_BlendFunc(GL_ONE, GL_ZERO);
9604                 GL_DepthMask(writedepth);
9605         }
9606
9607         if (r_showsurfaces.integer == 3)
9608         {
9609                 rsurface.passcolor4f = NULL;
9610
9611                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9612                 {
9613                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9614
9615                         rsurface.passcolor4f = NULL;
9616                         rsurface.passcolor4f_vertexbuffer = 0;
9617                         rsurface.passcolor4f_bufferoffset = 0;
9618                 }
9619                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9620                 {
9621                         qboolean applycolor = true;
9622                         float one = 1.0;
9623
9624                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9625
9626                         r_refdef.lightmapintensity = 1;
9627                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9628                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9629                 }
9630                 else if (FAKELIGHT_ENABLED)
9631                 {
9632                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9633
9634                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9635                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9636                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9637                 }
9638                 else
9639                 {
9640                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9641
9642                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9643                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9644                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9645                 }
9646
9647                 if(!rsurface.passcolor4f)
9648                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9649
9650                 RSurf_DrawBatch_GL11_ApplyAmbient();
9651                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9652                 if(r_refdef.fogenabled)
9653                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9654                 RSurf_DrawBatch_GL11_ClampColor();
9655
9656                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9657                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9658                 RSurf_DrawBatch();
9659         }
9660         else if (!r_refdef.view.showdebug)
9661         {
9662                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9663                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9664                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9665                 {
9666                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9667                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9668                 }
9669                 R_Mesh_PrepareVertices_Generic_Unlock();
9670                 RSurf_DrawBatch();
9671         }
9672         else if (r_showsurfaces.integer == 4)
9673         {
9674                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9675                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9676                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9677                 {
9678                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9679                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9680                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9681                 }
9682                 R_Mesh_PrepareVertices_Generic_Unlock();
9683                 RSurf_DrawBatch();
9684         }
9685         else if (r_showsurfaces.integer == 2)
9686         {
9687                 const int *e;
9688                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9689                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9690                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9691                 {
9692                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9693                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9694                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9695                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9696                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9697                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9698                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9699                 }
9700                 R_Mesh_PrepareVertices_Generic_Unlock();
9701                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9702         }
9703         else
9704         {
9705                 int texturesurfaceindex;
9706                 int k;
9707                 const msurface_t *surface;
9708                 float surfacecolor4f[4];
9709                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9710                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9711                 vi = 0;
9712                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9713                 {
9714                         surface = texturesurfacelist[texturesurfaceindex];
9715                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9716                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9717                         for (j = 0;j < surface->num_vertices;j++)
9718                         {
9719                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9720                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9721                                 vi++;
9722                         }
9723                 }
9724                 R_Mesh_PrepareVertices_Generic_Unlock();
9725                 RSurf_DrawBatch();
9726         }
9727 }
9728
9729 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9730 {
9731         CHECKGLERROR
9732         RSurf_SetupDepthAndCulling();
9733         if (r_showsurfaces.integer)
9734         {
9735                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9736                 return;
9737         }
9738         switch (vid.renderpath)
9739         {
9740         case RENDERPATH_GL20:
9741         case RENDERPATH_D3D9:
9742         case RENDERPATH_D3D10:
9743         case RENDERPATH_D3D11:
9744         case RENDERPATH_SOFT:
9745         case RENDERPATH_GLES2:
9746                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9747                 break;
9748         case RENDERPATH_GL13:
9749                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9750                 break;
9751         case RENDERPATH_GL11:
9752                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9753                 break;
9754         }
9755         CHECKGLERROR
9756 }
9757
9758 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9759 {
9760         CHECKGLERROR
9761         RSurf_SetupDepthAndCulling();
9762         if (r_showsurfaces.integer)
9763         {
9764                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9765                 return;
9766         }
9767         switch (vid.renderpath)
9768         {
9769         case RENDERPATH_GL20:
9770         case RENDERPATH_D3D9:
9771         case RENDERPATH_D3D10:
9772         case RENDERPATH_D3D11:
9773         case RENDERPATH_SOFT:
9774         case RENDERPATH_GLES2:
9775                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9776                 break;
9777         case RENDERPATH_GL13:
9778                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9779                 break;
9780         case RENDERPATH_GL11:
9781                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9782                 break;
9783         }
9784         CHECKGLERROR
9785 }
9786
9787 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9788 {
9789         int i, j;
9790         int texturenumsurfaces, endsurface;
9791         texture_t *texture;
9792         const msurface_t *surface;
9793 #define MAXBATCH_TRANSPARENTSURFACES 256
9794         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9795
9796         // if the model is static it doesn't matter what value we give for
9797         // wantnormals and wanttangents, so this logic uses only rules applicable
9798         // to a model, knowing that they are meaningless otherwise
9799         if (ent == r_refdef.scene.worldentity)
9800                 RSurf_ActiveWorldEntity();
9801         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9802                 RSurf_ActiveModelEntity(ent, false, false, false);
9803         else
9804         {
9805                 switch (vid.renderpath)
9806                 {
9807                 case RENDERPATH_GL20:
9808                 case RENDERPATH_D3D9:
9809                 case RENDERPATH_D3D10:
9810                 case RENDERPATH_D3D11:
9811                 case RENDERPATH_SOFT:
9812                 case RENDERPATH_GLES2:
9813                         RSurf_ActiveModelEntity(ent, true, true, false);
9814                         break;
9815                 case RENDERPATH_GL13:
9816                 case RENDERPATH_GL11:
9817                         RSurf_ActiveModelEntity(ent, true, false, false);
9818                         break;
9819                 }
9820         }
9821
9822         if (r_transparentdepthmasking.integer)
9823         {
9824                 qboolean setup = false;
9825                 for (i = 0;i < numsurfaces;i = j)
9826                 {
9827                         j = i + 1;
9828                         surface = rsurface.modelsurfaces + surfacelist[i];
9829                         texture = surface->texture;
9830                         rsurface.texture = R_GetCurrentTexture(texture);
9831                         rsurface.lightmaptexture = NULL;
9832                         rsurface.deluxemaptexture = NULL;
9833                         rsurface.uselightmaptexture = false;
9834                         // scan ahead until we find a different texture
9835                         endsurface = min(i + 1024, numsurfaces);
9836                         texturenumsurfaces = 0;
9837                         texturesurfacelist[texturenumsurfaces++] = surface;
9838                         for (;j < endsurface;j++)
9839                         {
9840                                 surface = rsurface.modelsurfaces + surfacelist[j];
9841                                 if (texture != surface->texture)
9842                                         break;
9843                                 texturesurfacelist[texturenumsurfaces++] = surface;
9844                         }
9845                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9846                                 continue;
9847                         // render the range of surfaces as depth
9848                         if (!setup)
9849                         {
9850                                 setup = true;
9851                                 GL_ColorMask(0,0,0,0);
9852                                 GL_Color(1,1,1,1);
9853                                 GL_DepthTest(true);
9854                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9855                                 GL_DepthMask(true);
9856 //                              R_Mesh_ResetTextureState();
9857                                 R_SetupShader_DepthOrShadow();
9858                         }
9859                         RSurf_SetupDepthAndCulling();
9860                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9861                         if (rsurface.batchvertex3fbuffer)
9862                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9863                         else
9864                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9865                         RSurf_DrawBatch();
9866                 }
9867                 if (setup)
9868                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9869         }
9870
9871         for (i = 0;i < numsurfaces;i = j)
9872         {
9873                 j = i + 1;
9874                 surface = rsurface.modelsurfaces + surfacelist[i];
9875                 texture = surface->texture;
9876                 rsurface.texture = R_GetCurrentTexture(texture);
9877                 // scan ahead until we find a different texture
9878                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9879                 texturenumsurfaces = 0;
9880                 texturesurfacelist[texturenumsurfaces++] = surface;
9881                 if(FAKELIGHT_ENABLED)
9882                 {
9883                         rsurface.lightmaptexture = NULL;
9884                         rsurface.deluxemaptexture = NULL;
9885                         rsurface.uselightmaptexture = false;
9886                         for (;j < endsurface;j++)
9887                         {
9888                                 surface = rsurface.modelsurfaces + surfacelist[j];
9889                                 if (texture != surface->texture)
9890                                         break;
9891                                 texturesurfacelist[texturenumsurfaces++] = surface;
9892                         }
9893                 }
9894                 else
9895                 {
9896                         rsurface.lightmaptexture = surface->lightmaptexture;
9897                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9898                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9899                         for (;j < endsurface;j++)
9900                         {
9901                                 surface = rsurface.modelsurfaces + surfacelist[j];
9902                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9903                                         break;
9904                                 texturesurfacelist[texturenumsurfaces++] = surface;
9905                         }
9906                 }
9907                 // render the range of surfaces
9908                 if (ent == r_refdef.scene.worldentity)
9909                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9910                 else
9911                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9912         }
9913         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9914 }
9915
9916 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9917 {
9918         // transparent surfaces get pushed off into the transparent queue
9919         int surfacelistindex;
9920         const msurface_t *surface;
9921         vec3_t tempcenter, center;
9922         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9923         {
9924                 surface = texturesurfacelist[surfacelistindex];
9925                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9926                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9927                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9928                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9929                 if (queueentity->transparent_offset) // transparent offset
9930                 {
9931                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9932                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9933                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9934                 }
9935                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9936         }
9937 }
9938
9939 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9940 {
9941         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9942                 return;
9943         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9944                 return;
9945         RSurf_SetupDepthAndCulling();
9946         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9947         if (rsurface.batchvertex3fbuffer)
9948                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9949         else
9950                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9951         RSurf_DrawBatch();
9952 }
9953
9954 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9955 {
9956         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9957         CHECKGLERROR
9958         if (depthonly)
9959                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9960         else if (prepass)
9961         {
9962                 if (!rsurface.texture->currentnumlayers)
9963                         return;
9964                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9965                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9966                 else
9967                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9968         }
9969         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9970                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9971         else if (!rsurface.texture->currentnumlayers)
9972                 return;
9973         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9974         {
9975                 // in the deferred case, transparent surfaces were queued during prepass
9976                 if (!r_shadow_usingdeferredprepass)
9977                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9978         }
9979         else
9980         {
9981                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9982                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9983         }
9984         CHECKGLERROR
9985 }
9986
9987 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9988 {
9989         int i, j;
9990         texture_t *texture;
9991         R_FrameData_SetMark();
9992         // break the surface list down into batches by texture and use of lightmapping
9993         for (i = 0;i < numsurfaces;i = j)
9994         {
9995                 j = i + 1;
9996                 // texture is the base texture pointer, rsurface.texture is the
9997                 // current frame/skin the texture is directing us to use (for example
9998                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9999                 // use skin 1 instead)
10000                 texture = surfacelist[i]->texture;
10001                 rsurface.texture = R_GetCurrentTexture(texture);
10002                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10003                 {
10004                         // if this texture is not the kind we want, skip ahead to the next one
10005                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10006                                 ;
10007                         continue;
10008                 }
10009                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10010                 {
10011                         rsurface.lightmaptexture = NULL;
10012                         rsurface.deluxemaptexture = NULL;
10013                         rsurface.uselightmaptexture = false;
10014                         // simply scan ahead until we find a different texture or lightmap state
10015                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10016                                 ;
10017                 }
10018                 else
10019                 {
10020                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10021                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10022                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10023                         // simply scan ahead until we find a different texture or lightmap state
10024                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10025                                 ;
10026                 }
10027                 // render the range of surfaces
10028                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10029         }
10030         R_FrameData_ReturnToMark();
10031 }
10032
10033 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10034 {
10035         CHECKGLERROR
10036         if (depthonly)
10037                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10038         else if (prepass)
10039         {
10040                 if (!rsurface.texture->currentnumlayers)
10041                         return;
10042                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10043                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10044                 else
10045                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10046         }
10047         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10048                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10049         else if (!rsurface.texture->currentnumlayers)
10050                 return;
10051         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10052         {
10053                 // in the deferred case, transparent surfaces were queued during prepass
10054                 if (!r_shadow_usingdeferredprepass)
10055                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10056         }
10057         else
10058         {
10059                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10060                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10061         }
10062         CHECKGLERROR
10063 }
10064
10065 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10066 {
10067         int i, j;
10068         texture_t *texture;
10069         R_FrameData_SetMark();
10070         // break the surface list down into batches by texture and use of lightmapping
10071         for (i = 0;i < numsurfaces;i = j)
10072         {
10073                 j = i + 1;
10074                 // texture is the base texture pointer, rsurface.texture is the
10075                 // current frame/skin the texture is directing us to use (for example
10076                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10077                 // use skin 1 instead)
10078                 texture = surfacelist[i]->texture;
10079                 rsurface.texture = R_GetCurrentTexture(texture);
10080                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10081                 {
10082                         // if this texture is not the kind we want, skip ahead to the next one
10083                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10084                                 ;
10085                         continue;
10086                 }
10087                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10088                 {
10089                         rsurface.lightmaptexture = NULL;
10090                         rsurface.deluxemaptexture = NULL;
10091                         rsurface.uselightmaptexture = false;
10092                         // simply scan ahead until we find a different texture or lightmap state
10093                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10094                                 ;
10095                 }
10096                 else
10097                 {
10098                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10099                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10100                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10101                         // simply scan ahead until we find a different texture or lightmap state
10102                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10103                                 ;
10104                 }
10105                 // render the range of surfaces
10106                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10107         }
10108         R_FrameData_ReturnToMark();
10109 }
10110
10111 float locboxvertex3f[6*4*3] =
10112 {
10113         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10114         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10115         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10116         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10117         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10118         1,0,0, 0,0,0, 0,1,0, 1,1,0
10119 };
10120
10121 unsigned short locboxelements[6*2*3] =
10122 {
10123          0, 1, 2, 0, 2, 3,
10124          4, 5, 6, 4, 6, 7,
10125          8, 9,10, 8,10,11,
10126         12,13,14, 12,14,15,
10127         16,17,18, 16,18,19,
10128         20,21,22, 20,22,23
10129 };
10130
10131 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10132 {
10133         int i, j;
10134         cl_locnode_t *loc = (cl_locnode_t *)ent;
10135         vec3_t mins, size;
10136         float vertex3f[6*4*3];
10137         CHECKGLERROR
10138         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10139         GL_DepthMask(false);
10140         GL_DepthRange(0, 1);
10141         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10142         GL_DepthTest(true);
10143         GL_CullFace(GL_NONE);
10144         R_EntityMatrix(&identitymatrix);
10145
10146 //      R_Mesh_ResetTextureState();
10147
10148         i = surfacelist[0];
10149         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10150                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10151                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10152                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10153
10154         if (VectorCompare(loc->mins, loc->maxs))
10155         {
10156                 VectorSet(size, 2, 2, 2);
10157                 VectorMA(loc->mins, -0.5f, size, mins);
10158         }
10159         else
10160         {
10161                 VectorCopy(loc->mins, mins);
10162                 VectorSubtract(loc->maxs, loc->mins, size);
10163         }
10164
10165         for (i = 0;i < 6*4*3;)
10166                 for (j = 0;j < 3;j++, i++)
10167                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10168
10169         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10170         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10171         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10172 }
10173
10174 void R_DrawLocs(void)
10175 {
10176         int index;
10177         cl_locnode_t *loc, *nearestloc;
10178         vec3_t center;
10179         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10180         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10181         {
10182                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10183                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10184         }
10185 }
10186
10187 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10188 {
10189         if (decalsystem->decals)
10190                 Mem_Free(decalsystem->decals);
10191         memset(decalsystem, 0, sizeof(*decalsystem));
10192 }
10193
10194 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)
10195 {
10196         tridecal_t *decal;
10197         tridecal_t *decals;
10198         int i;
10199
10200         // expand or initialize the system
10201         if (decalsystem->maxdecals <= decalsystem->numdecals)
10202         {
10203                 decalsystem_t old = *decalsystem;
10204                 qboolean useshortelements;
10205                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10206                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10207                 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)));
10208                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10209                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10210                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10211                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10212                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10213                 if (decalsystem->numdecals)
10214                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10215                 if (old.decals)
10216                         Mem_Free(old.decals);
10217                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10218                         decalsystem->element3i[i] = i;
10219                 if (useshortelements)
10220                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10221                                 decalsystem->element3s[i] = i;
10222         }
10223
10224         // grab a decal and search for another free slot for the next one
10225         decals = decalsystem->decals;
10226         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10227         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10228                 ;
10229         decalsystem->freedecal = i;
10230         if (decalsystem->numdecals <= i)
10231                 decalsystem->numdecals = i + 1;
10232
10233         // initialize the decal
10234         decal->lived = 0;
10235         decal->triangleindex = triangleindex;
10236         decal->surfaceindex = surfaceindex;
10237         decal->decalsequence = decalsequence;
10238         decal->color4f[0][0] = c0[0];
10239         decal->color4f[0][1] = c0[1];
10240         decal->color4f[0][2] = c0[2];
10241         decal->color4f[0][3] = 1;
10242         decal->color4f[1][0] = c1[0];
10243         decal->color4f[1][1] = c1[1];
10244         decal->color4f[1][2] = c1[2];
10245         decal->color4f[1][3] = 1;
10246         decal->color4f[2][0] = c2[0];
10247         decal->color4f[2][1] = c2[1];
10248         decal->color4f[2][2] = c2[2];
10249         decal->color4f[2][3] = 1;
10250         decal->vertex3f[0][0] = v0[0];
10251         decal->vertex3f[0][1] = v0[1];
10252         decal->vertex3f[0][2] = v0[2];
10253         decal->vertex3f[1][0] = v1[0];
10254         decal->vertex3f[1][1] = v1[1];
10255         decal->vertex3f[1][2] = v1[2];
10256         decal->vertex3f[2][0] = v2[0];
10257         decal->vertex3f[2][1] = v2[1];
10258         decal->vertex3f[2][2] = v2[2];
10259         decal->texcoord2f[0][0] = t0[0];
10260         decal->texcoord2f[0][1] = t0[1];
10261         decal->texcoord2f[1][0] = t1[0];
10262         decal->texcoord2f[1][1] = t1[1];
10263         decal->texcoord2f[2][0] = t2[0];
10264         decal->texcoord2f[2][1] = t2[1];
10265 }
10266
10267 extern cvar_t cl_decals_bias;
10268 extern cvar_t cl_decals_models;
10269 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10270 // baseparms, parms, temps
10271 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)
10272 {
10273         int cornerindex;
10274         int index;
10275         float v[9][3];
10276         const float *vertex3f;
10277         const float *normal3f;
10278         int numpoints;
10279         float points[2][9][3];
10280         float temp[3];
10281         float tc[9][2];
10282         float f;
10283         float c[9][4];
10284         const int *e;
10285
10286         e = rsurface.modelelement3i + 3*triangleindex;
10287
10288         vertex3f = rsurface.modelvertex3f;
10289         normal3f = rsurface.modelnormal3f;
10290
10291         if (normal3f)
10292         {
10293                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10294                 {
10295                         index = 3*e[cornerindex];
10296                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10297                 }
10298         }
10299         else
10300         {
10301                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10302                 {
10303                         index = 3*e[cornerindex];
10304                         VectorCopy(vertex3f + index, v[cornerindex]);
10305                 }
10306         }
10307
10308         // cull backfaces
10309         //TriangleNormal(v[0], v[1], v[2], normal);
10310         //if (DotProduct(normal, localnormal) < 0.0f)
10311         //      continue;
10312         // clip by each of the box planes formed from the projection matrix
10313         // if anything survives, we emit the decal
10314         numpoints = PolygonF_Clip(3        , v[0]        , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10315         if (numpoints < 3)
10316                 return;
10317         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
10318         if (numpoints < 3)
10319                 return;
10320         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10321         if (numpoints < 3)
10322                 return;
10323         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
10324         if (numpoints < 3)
10325                 return;
10326         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10327         if (numpoints < 3)
10328                 return;
10329         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
10330         if (numpoints < 3)
10331                 return;
10332         // some part of the triangle survived, so we have to accept it...
10333         if (dynamic)
10334         {
10335                 // dynamic always uses the original triangle
10336                 numpoints = 3;
10337                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10338                 {
10339                         index = 3*e[cornerindex];
10340                         VectorCopy(vertex3f + index, v[cornerindex]);
10341                 }
10342         }
10343         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10344         {
10345                 // convert vertex positions to texcoords
10346                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10347                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10348                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10349                 // calculate distance fade from the projection origin
10350                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10351                 f = bound(0.0f, f, 1.0f);
10352                 c[cornerindex][0] = r * f;
10353                 c[cornerindex][1] = g * f;
10354                 c[cornerindex][2] = b * f;
10355                 c[cornerindex][3] = 1.0f;
10356                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10357         }
10358         if (dynamic)
10359                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
10360         else
10361                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10362                         R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
10363 }
10364 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10365 {
10366         matrix4x4_t projection;
10367         decalsystem_t *decalsystem;
10368         qboolean dynamic;
10369         dp_model_t *model;
10370         const msurface_t *surface;
10371         const msurface_t *surfaces;
10372         const int *surfacelist;
10373         const texture_t *texture;
10374         int numtriangles;
10375         int numsurfacelist;
10376         int surfacelistindex;
10377         int surfaceindex;
10378         int triangleindex;
10379         float localorigin[3];
10380         float localnormal[3];
10381         float localmins[3];
10382         float localmaxs[3];
10383         float localsize;
10384         //float normal[3];
10385         float planes[6][4];
10386         float angles[3];
10387         bih_t *bih;
10388         int bih_triangles_count;
10389         int bih_triangles[256];
10390         int bih_surfaces[256];
10391
10392         decalsystem = &ent->decalsystem;
10393         model = ent->model;
10394         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10395         {
10396                 R_DecalSystem_Reset(&ent->decalsystem);
10397                 return;
10398         }
10399
10400         if (!model->brush.data_leafs && !cl_decals_models.integer)
10401         {
10402                 if (decalsystem->model)
10403                         R_DecalSystem_Reset(decalsystem);
10404                 return;
10405         }
10406
10407         if (decalsystem->model != model)
10408                 R_DecalSystem_Reset(decalsystem);
10409         decalsystem->model = model;
10410
10411         RSurf_ActiveModelEntity(ent, true, false, false);
10412
10413         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10414         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10415         VectorNormalize(localnormal);
10416         localsize = worldsize*rsurface.inversematrixscale;
10417         localmins[0] = localorigin[0] - localsize;
10418         localmins[1] = localorigin[1] - localsize;
10419         localmins[2] = localorigin[2] - localsize;
10420         localmaxs[0] = localorigin[0] + localsize;
10421         localmaxs[1] = localorigin[1] + localsize;
10422         localmaxs[2] = localorigin[2] + localsize;
10423
10424         //VectorCopy(localnormal, planes[4]);
10425         //VectorVectors(planes[4], planes[2], planes[0]);
10426         AnglesFromVectors(angles, localnormal, NULL, false);
10427         AngleVectors(angles, planes[0], planes[2], planes[4]);
10428         VectorNegate(planes[0], planes[1]);
10429         VectorNegate(planes[2], planes[3]);
10430         VectorNegate(planes[4], planes[5]);
10431         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10432         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10433         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10434         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10435         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10436         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10437
10438 #if 1
10439 // works
10440 {
10441         matrix4x4_t forwardprojection;
10442         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10443         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10444 }
10445 #else
10446 // broken
10447 {
10448         float projectionvector[4][3];
10449         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10450         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10451         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10452         projectionvector[0][0] = planes[0][0] * ilocalsize;
10453         projectionvector[0][1] = planes[1][0] * ilocalsize;
10454         projectionvector[0][2] = planes[2][0] * ilocalsize;
10455         projectionvector[1][0] = planes[0][1] * ilocalsize;
10456         projectionvector[1][1] = planes[1][1] * ilocalsize;
10457         projectionvector[1][2] = planes[2][1] * ilocalsize;
10458         projectionvector[2][0] = planes[0][2] * ilocalsize;
10459         projectionvector[2][1] = planes[1][2] * ilocalsize;
10460         projectionvector[2][2] = planes[2][2] * ilocalsize;
10461         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10462         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10463         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10464         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10465 }
10466 #endif
10467
10468         dynamic = model->surfmesh.isanimated;
10469         numsurfacelist = model->nummodelsurfaces;
10470         surfacelist = model->sortedmodelsurfaces;
10471         surfaces = model->data_surfaces;
10472
10473         bih = NULL;
10474         bih_triangles_count = -1;
10475         if(!dynamic)
10476         {
10477                 if(model->render_bih.numleafs)
10478                         bih = &model->render_bih;
10479                 else if(model->collision_bih.numleafs)
10480                         bih = &model->collision_bih;
10481         }
10482         if(bih)
10483                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10484         if(bih_triangles_count == 0)
10485                 return;
10486         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10487                 return;
10488         if(bih_triangles_count > 0)
10489         {
10490                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10491                 {
10492                         surfaceindex = bih_surfaces[triangleindex];
10493                         surface = surfaces + surfaceindex;
10494                         texture = surface->texture;
10495                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10496                                 continue;
10497                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10498                                 continue;
10499                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10500                 }
10501         }
10502         else
10503         {
10504                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10505                 {
10506                         surfaceindex = surfacelist[surfacelistindex];
10507                         surface = surfaces + surfaceindex;
10508                         // check cull box first because it rejects more than any other check
10509                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10510                                 continue;
10511                         // skip transparent surfaces
10512                         texture = surface->texture;
10513                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10514                                 continue;
10515                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10516                                 continue;
10517                         numtriangles = surface->num_triangles;
10518                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10519                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10520                 }
10521         }
10522 }
10523
10524 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10525 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10526 {
10527         int renderentityindex;
10528         float worldmins[3];
10529         float worldmaxs[3];
10530         entity_render_t *ent;
10531
10532         if (!cl_decals_newsystem.integer)
10533                 return;
10534
10535         worldmins[0] = worldorigin[0] - worldsize;
10536         worldmins[1] = worldorigin[1] - worldsize;
10537         worldmins[2] = worldorigin[2] - worldsize;
10538         worldmaxs[0] = worldorigin[0] + worldsize;
10539         worldmaxs[1] = worldorigin[1] + worldsize;
10540         worldmaxs[2] = worldorigin[2] + worldsize;
10541
10542         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10543
10544         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10545         {
10546                 ent = r_refdef.scene.entities[renderentityindex];
10547                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10548                         continue;
10549
10550                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10551         }
10552 }
10553
10554 typedef struct r_decalsystem_splatqueue_s
10555 {
10556         vec3_t worldorigin;
10557         vec3_t worldnormal;
10558         float color[4];
10559         float tcrange[4];
10560         float worldsize;
10561         int decalsequence;
10562 }
10563 r_decalsystem_splatqueue_t;
10564
10565 int r_decalsystem_numqueued = 0;
10566 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10567
10568 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
10569 {
10570         r_decalsystem_splatqueue_t *queue;
10571
10572         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10573                 return;
10574
10575         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10576         VectorCopy(worldorigin, queue->worldorigin);
10577         VectorCopy(worldnormal, queue->worldnormal);
10578         Vector4Set(queue->color, r, g, b, a);
10579         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10580         queue->worldsize = worldsize;
10581         queue->decalsequence = cl.decalsequence++;
10582 }
10583
10584 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10585 {
10586         int i;
10587         r_decalsystem_splatqueue_t *queue;
10588
10589         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10590                 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
10591         r_decalsystem_numqueued = 0;
10592 }
10593
10594 extern cvar_t cl_decals_max;
10595 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10596 {
10597         int i;
10598         decalsystem_t *decalsystem = &ent->decalsystem;
10599         int numdecals;
10600         int killsequence;
10601         tridecal_t *decal;
10602         float frametime;
10603         float lifetime;
10604
10605         if (!decalsystem->numdecals)
10606                 return;
10607
10608         if (r_showsurfaces.integer)
10609                 return;
10610
10611         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10612         {
10613                 R_DecalSystem_Reset(decalsystem);
10614                 return;
10615         }
10616
10617         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10618         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10619
10620         if (decalsystem->lastupdatetime)
10621                 frametime = (cl.time - decalsystem->lastupdatetime);
10622         else
10623                 frametime = 0;
10624         decalsystem->lastupdatetime = cl.time;
10625         decal = decalsystem->decals;
10626         numdecals = decalsystem->numdecals;
10627
10628         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10629         {
10630                 if (decal->color4f[0][3])
10631                 {
10632                         decal->lived += frametime;
10633                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10634                         {
10635                                 memset(decal, 0, sizeof(*decal));
10636                                 if (decalsystem->freedecal > i)
10637                                         decalsystem->freedecal = i;
10638                         }
10639                 }
10640         }
10641         decal = decalsystem->decals;
10642         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10643                 numdecals--;
10644
10645         // collapse the array by shuffling the tail decals into the gaps
10646         for (;;)
10647         {
10648                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10649                         decalsystem->freedecal++;
10650                 if (decalsystem->freedecal == numdecals)
10651                         break;
10652                 decal[decalsystem->freedecal] = decal[--numdecals];
10653         }
10654
10655         decalsystem->numdecals = numdecals;
10656
10657         if (numdecals <= 0)
10658         {
10659                 // if there are no decals left, reset decalsystem
10660                 R_DecalSystem_Reset(decalsystem);
10661         }
10662 }
10663
10664 extern skinframe_t *decalskinframe;
10665 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10666 {
10667         int i;
10668         decalsystem_t *decalsystem = &ent->decalsystem;
10669         int numdecals;
10670         tridecal_t *decal;
10671         float faderate;
10672         float alpha;
10673         float *v3f;
10674         float *c4f;
10675         float *t2f;
10676         const int *e;
10677         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10678         int numtris = 0;
10679
10680         numdecals = decalsystem->numdecals;
10681         if (!numdecals)
10682                 return;
10683
10684         if (r_showsurfaces.integer)
10685                 return;
10686
10687         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10688         {
10689                 R_DecalSystem_Reset(decalsystem);
10690                 return;
10691         }
10692
10693         // if the model is static it doesn't matter what value we give for
10694         // wantnormals and wanttangents, so this logic uses only rules applicable
10695         // to a model, knowing that they are meaningless otherwise
10696         if (ent == r_refdef.scene.worldentity)
10697                 RSurf_ActiveWorldEntity();
10698         else
10699                 RSurf_ActiveModelEntity(ent, false, false, false);
10700
10701         decalsystem->lastupdatetime = cl.time;
10702         decal = decalsystem->decals;
10703
10704         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10705
10706         // update vertex positions for animated models
10707         v3f = decalsystem->vertex3f;
10708         c4f = decalsystem->color4f;
10709         t2f = decalsystem->texcoord2f;
10710         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10711         {
10712                 if (!decal->color4f[0][3])
10713                         continue;
10714
10715                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10716                         continue;
10717
10718                 // update color values for fading decals
10719                 if (decal->lived >= cl_decals_time.value)
10720                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10721                 else
10722                         alpha = 1.0f;
10723
10724                 c4f[ 0] = decal->color4f[0][0] * alpha;
10725                 c4f[ 1] = decal->color4f[0][1] * alpha;
10726                 c4f[ 2] = decal->color4f[0][2] * alpha;
10727                 c4f[ 3] = 1;
10728                 c4f[ 4] = decal->color4f[1][0] * alpha;
10729                 c4f[ 5] = decal->color4f[1][1] * alpha;
10730                 c4f[ 6] = decal->color4f[1][2] * alpha;
10731                 c4f[ 7] = 1;
10732                 c4f[ 8] = decal->color4f[2][0] * alpha;
10733                 c4f[ 9] = decal->color4f[2][1] * alpha;
10734                 c4f[10] = decal->color4f[2][2] * alpha;
10735                 c4f[11] = 1;
10736
10737                 t2f[0] = decal->texcoord2f[0][0];
10738                 t2f[1] = decal->texcoord2f[0][1];
10739                 t2f[2] = decal->texcoord2f[1][0];
10740                 t2f[3] = decal->texcoord2f[1][1];
10741                 t2f[4] = decal->texcoord2f[2][0];
10742                 t2f[5] = decal->texcoord2f[2][1];
10743
10744                 // update vertex positions for animated models
10745                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10746                 {
10747                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10748                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10749                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10750                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10751                 }
10752                 else
10753                 {
10754                         VectorCopy(decal->vertex3f[0], v3f);
10755                         VectorCopy(decal->vertex3f[1], v3f + 3);
10756                         VectorCopy(decal->vertex3f[2], v3f + 6);
10757                 }
10758
10759                 if (r_refdef.fogenabled)
10760                 {
10761                         alpha = RSurf_FogVertex(v3f);
10762                         VectorScale(c4f, alpha, c4f);
10763                         alpha = RSurf_FogVertex(v3f + 3);
10764                         VectorScale(c4f + 4, alpha, c4f + 4);
10765                         alpha = RSurf_FogVertex(v3f + 6);
10766                         VectorScale(c4f + 8, alpha, c4f + 8);
10767                 }
10768
10769                 v3f += 9;
10770                 c4f += 12;
10771                 t2f += 6;
10772                 numtris++;
10773         }
10774
10775         if (numtris > 0)
10776         {
10777                 r_refdef.stats.drawndecals += numtris;
10778
10779                 // now render the decals all at once
10780                 // (this assumes they all use one particle font texture!)
10781                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
10782 //              R_Mesh_ResetTextureState();
10783                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10784                 GL_DepthMask(false);
10785                 GL_DepthRange(0, 1);
10786                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10787                 GL_DepthTest(true);
10788                 GL_CullFace(GL_NONE);
10789                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10790                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10791                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10792         }
10793 }
10794
10795 static void R_DrawModelDecals(void)
10796 {
10797         int i, numdecals;
10798
10799         // fade faster when there are too many decals
10800         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10801         for (i = 0;i < r_refdef.scene.numentities;i++)
10802                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10803
10804         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10805         for (i = 0;i < r_refdef.scene.numentities;i++)
10806                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10807                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10808
10809         R_DecalSystem_ApplySplatEntitiesQueue();
10810
10811         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10812         for (i = 0;i < r_refdef.scene.numentities;i++)
10813                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10814
10815         r_refdef.stats.totaldecals += numdecals;
10816
10817         if (r_showsurfaces.integer)
10818                 return;
10819
10820         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10821
10822         for (i = 0;i < r_refdef.scene.numentities;i++)
10823         {
10824                 if (!r_refdef.viewcache.entityvisible[i])
10825                         continue;
10826                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10827                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10828         }
10829 }
10830
10831 extern cvar_t mod_collision_bih;
10832 void R_DrawDebugModel(void)
10833 {
10834         entity_render_t *ent = rsurface.entity;
10835         int i, j, k, l, flagsmask;
10836         const msurface_t *surface;
10837         dp_model_t *model = ent->model;
10838         vec3_t v;
10839
10840         switch(vid.renderpath)
10841         {
10842         case RENDERPATH_GL11:
10843         case RENDERPATH_GL13:
10844         case RENDERPATH_GL20:
10845                 break;
10846         case RENDERPATH_D3D9:
10847                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10848                 return;
10849         case RENDERPATH_D3D10:
10850                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10851                 return;
10852         case RENDERPATH_D3D11:
10853                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10854                 return;
10855         case RENDERPATH_SOFT:
10856                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10857                 return;
10858         case RENDERPATH_GLES2:
10859                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10860                 return;
10861         }
10862
10863         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10864
10865 //      R_Mesh_ResetTextureState();
10866         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10867         GL_DepthRange(0, 1);
10868         GL_DepthTest(!r_showdisabledepthtest.integer);
10869         GL_DepthMask(false);
10870         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10871
10872         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10873         {
10874                 int triangleindex;
10875                 int bihleafindex;
10876                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10877                 const q3mbrush_t *brush;
10878                 const bih_t *bih = &model->collision_bih;
10879                 const bih_leaf_t *bihleaf;
10880                 float vertex3f[3][3];
10881                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10882                 cullbox = false;
10883                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10884                 {
10885                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10886                                 continue;
10887                         switch (bihleaf->type)
10888                         {
10889                         case BIH_BRUSH:
10890                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10891                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10892                                 {
10893                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
10894                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10895                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10896                                 }
10897                                 break;
10898                         case BIH_COLLISIONTRIANGLE:
10899                                 triangleindex = bihleaf->itemindex;
10900                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10901                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10902                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10903                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
10904                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10905                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10906                                 break;
10907                         case BIH_RENDERTRIANGLE:
10908                                 triangleindex = bihleaf->itemindex;
10909                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10910                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10911                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10912                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
10913                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10914                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10915                                 break;
10916                         }
10917                 }
10918         }
10919
10920         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10921
10922         if (r_showtris.integer || (r_shownormals.value != 0))
10923         {
10924                 if (r_showdisabledepthtest.integer)
10925                 {
10926                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10927                         GL_DepthMask(false);
10928                 }
10929                 else
10930                 {
10931                         GL_BlendFunc(GL_ONE, GL_ZERO);
10932                         GL_DepthMask(true);
10933                 }
10934                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10935                 {
10936                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10937                                 continue;
10938                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10939                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10940                         {
10941                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10942                                 if (r_showtris.value > 0)
10943                                 {
10944                                         if (!rsurface.texture->currentlayers->depthmask)
10945                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10946                                         else if (ent == r_refdef.scene.worldentity)
10947                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10948                                         else
10949                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10950                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10951                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10952                                         RSurf_DrawBatch();
10953                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10954                                         CHECKGLERROR
10955                                 }
10956                                 if (r_shownormals.value < 0)
10957                                 {
10958                                         qglBegin(GL_LINES);
10959                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10960                                         {
10961                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10962                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10963                                                 qglVertex3f(v[0], v[1], v[2]);
10964                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10965                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10966                                                 qglVertex3f(v[0], v[1], v[2]);
10967                                         }
10968                                         qglEnd();
10969                                         CHECKGLERROR
10970                                 }
10971                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10972                                 {
10973                                         qglBegin(GL_LINES);
10974                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10975                                         {
10976                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10977                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10978                                                 qglVertex3f(v[0], v[1], v[2]);
10979                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10980                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10981                                                 qglVertex3f(v[0], v[1], v[2]);
10982                                         }
10983                                         qglEnd();
10984                                         CHECKGLERROR
10985                                         qglBegin(GL_LINES);
10986                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10987                                         {
10988                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10989                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10990                                                 qglVertex3f(v[0], v[1], v[2]);
10991                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10992                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10993                                                 qglVertex3f(v[0], v[1], v[2]);
10994                                         }
10995                                         qglEnd();
10996                                         CHECKGLERROR
10997                                         qglBegin(GL_LINES);
10998                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10999                                         {
11000                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11001                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11002                                                 qglVertex3f(v[0], v[1], v[2]);
11003                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11004                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11005                                                 qglVertex3f(v[0], v[1], v[2]);
11006                                         }
11007                                         qglEnd();
11008                                         CHECKGLERROR
11009                                 }
11010                         }
11011                 }
11012                 rsurface.texture = NULL;
11013         }
11014 }
11015
11016 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11017 int r_maxsurfacelist = 0;
11018 const msurface_t **r_surfacelist = NULL;
11019 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11020 {
11021         int i, j, endj, flagsmask;
11022         dp_model_t *model = r_refdef.scene.worldmodel;
11023         msurface_t *surfaces;
11024         unsigned char *update;
11025         int numsurfacelist = 0;
11026         if (model == NULL)
11027                 return;
11028
11029         if (r_maxsurfacelist < model->num_surfaces)
11030         {
11031                 r_maxsurfacelist = model->num_surfaces;
11032                 if (r_surfacelist)
11033                         Mem_Free((msurface_t**)r_surfacelist);
11034                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11035         }
11036
11037         RSurf_ActiveWorldEntity();
11038
11039         surfaces = model->data_surfaces;
11040         update = model->brushq1.lightmapupdateflags;
11041
11042         // update light styles on this submodel
11043         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11044         {
11045                 model_brush_lightstyleinfo_t *style;
11046                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11047                 {
11048                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11049                         {
11050                                 int *list = style->surfacelist;
11051                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11052                                 for (j = 0;j < style->numsurfaces;j++)
11053                                         update[list[j]] = true;
11054                         }
11055                 }
11056         }
11057
11058         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11059
11060         if (debug)
11061         {
11062                 R_DrawDebugModel();
11063                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11064                 return;
11065         }
11066
11067         rsurface.lightmaptexture = NULL;
11068         rsurface.deluxemaptexture = NULL;
11069         rsurface.uselightmaptexture = false;
11070         rsurface.texture = NULL;
11071         rsurface.rtlight = NULL;
11072         numsurfacelist = 0;
11073         // add visible surfaces to draw list
11074         for (i = 0;i < model->nummodelsurfaces;i++)
11075         {
11076                 j = model->sortedmodelsurfaces[i];
11077                 if (r_refdef.viewcache.world_surfacevisible[j])
11078                         r_surfacelist[numsurfacelist++] = surfaces + j;
11079         }
11080         // update lightmaps if needed
11081         if (model->brushq1.firstrender)
11082         {
11083                 model->brushq1.firstrender = false;
11084                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11085                         if (update[j])
11086                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11087         }
11088         else if (update)
11089         {
11090                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11091                         if (r_refdef.viewcache.world_surfacevisible[j])
11092                                 if (update[j])
11093                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11094         }
11095         // don't do anything if there were no surfaces
11096         if (!numsurfacelist)
11097         {
11098                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11099                 return;
11100         }
11101         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11102
11103         // add to stats if desired
11104         if (r_speeds.integer && !skysurfaces && !depthonly)
11105         {
11106                 r_refdef.stats.world_surfaces += numsurfacelist;
11107                 for (j = 0;j < numsurfacelist;j++)
11108                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11109         }
11110
11111         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11112 }
11113
11114 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11115 {
11116         int i, j, endj, flagsmask;
11117         dp_model_t *model = ent->model;
11118         msurface_t *surfaces;
11119         unsigned char *update;
11120         int numsurfacelist = 0;
11121         if (model == NULL)
11122                 return;
11123
11124         if (r_maxsurfacelist < model->num_surfaces)
11125         {
11126                 r_maxsurfacelist = model->num_surfaces;
11127                 if (r_surfacelist)
11128                         Mem_Free((msurface_t **)r_surfacelist);
11129                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11130         }
11131
11132         // if the model is static it doesn't matter what value we give for
11133         // wantnormals and wanttangents, so this logic uses only rules applicable
11134         // to a model, knowing that they are meaningless otherwise
11135         if (ent == r_refdef.scene.worldentity)
11136                 RSurf_ActiveWorldEntity();
11137         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11138                 RSurf_ActiveModelEntity(ent, false, false, false);
11139         else if (prepass)
11140                 RSurf_ActiveModelEntity(ent, true, true, true);
11141         else if (depthonly)
11142         {
11143                 switch (vid.renderpath)
11144                 {
11145                 case RENDERPATH_GL20:
11146                 case RENDERPATH_D3D9:
11147                 case RENDERPATH_D3D10:
11148                 case RENDERPATH_D3D11:
11149                 case RENDERPATH_SOFT:
11150                 case RENDERPATH_GLES2:
11151                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11152                         break;
11153                 case RENDERPATH_GL13:
11154                 case RENDERPATH_GL11:
11155                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11156                         break;
11157                 }
11158         }
11159         else
11160         {
11161                 switch (vid.renderpath)
11162                 {
11163                 case RENDERPATH_GL20:
11164                 case RENDERPATH_D3D9:
11165                 case RENDERPATH_D3D10:
11166                 case RENDERPATH_D3D11:
11167                 case RENDERPATH_SOFT:
11168                 case RENDERPATH_GLES2:
11169                         RSurf_ActiveModelEntity(ent, true, true, false);
11170                         break;
11171                 case RENDERPATH_GL13:
11172                 case RENDERPATH_GL11:
11173                         RSurf_ActiveModelEntity(ent, true, false, false);
11174                         break;
11175                 }
11176         }
11177
11178         surfaces = model->data_surfaces;
11179         update = model->brushq1.lightmapupdateflags;
11180
11181         // update light styles
11182         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11183         {
11184                 model_brush_lightstyleinfo_t *style;
11185                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11186                 {
11187                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11188                         {
11189                                 int *list = style->surfacelist;
11190                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11191                                 for (j = 0;j < style->numsurfaces;j++)
11192                                         update[list[j]] = true;
11193                         }
11194                 }
11195         }
11196
11197         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11198
11199         if (debug)
11200         {
11201                 R_DrawDebugModel();
11202                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11203                 return;
11204         }
11205
11206         rsurface.lightmaptexture = NULL;
11207         rsurface.deluxemaptexture = NULL;
11208         rsurface.uselightmaptexture = false;
11209         rsurface.texture = NULL;
11210         rsurface.rtlight = NULL;
11211         numsurfacelist = 0;
11212         // add visible surfaces to draw list
11213         for (i = 0;i < model->nummodelsurfaces;i++)
11214                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11215         // don't do anything if there were no surfaces
11216         if (!numsurfacelist)
11217         {
11218                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11219                 return;
11220         }
11221         // update lightmaps if needed
11222         if (update)
11223         {
11224                 int updated = 0;
11225                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11226                 {
11227                         if (update[j])
11228                         {
11229                                 updated++;
11230                                 R_BuildLightMap(ent, surfaces + j);
11231                         }
11232                 }
11233         }
11234         if (update)
11235                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11236                         if (update[j])
11237                                 R_BuildLightMap(ent, surfaces + j);
11238         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11239
11240         // add to stats if desired
11241         if (r_speeds.integer && !skysurfaces && !depthonly)
11242         {
11243                 r_refdef.stats.entities_surfaces += numsurfacelist;
11244                 for (j = 0;j < numsurfacelist;j++)
11245                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11246         }
11247
11248         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11249 }
11250
11251 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11252 {
11253         static texture_t texture;
11254         static msurface_t surface;
11255         const msurface_t *surfacelist = &surface;
11256
11257         // fake enough texture and surface state to render this geometry
11258
11259         texture.update_lastrenderframe = -1; // regenerate this texture
11260         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11261         texture.currentskinframe = skinframe;
11262         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11263         texture.offsetmapping = OFFSETMAPPING_OFF;
11264         texture.offsetscale = 1;
11265         texture.specularscalemod = 1;
11266         texture.specularpowermod = 1;
11267
11268         surface.texture = &texture;
11269         surface.num_triangles = numtriangles;
11270         surface.num_firsttriangle = firsttriangle;
11271         surface.num_vertices = numvertices;
11272         surface.num_firstvertex = firstvertex;
11273
11274         // now render it
11275         rsurface.texture = R_GetCurrentTexture(surface.texture);
11276         rsurface.lightmaptexture = NULL;
11277         rsurface.deluxemaptexture = NULL;
11278         rsurface.uselightmaptexture = false;
11279         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11280 }
11281
11282 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11283 {
11284         static msurface_t surface;
11285         const msurface_t *surfacelist = &surface;
11286
11287         // fake enough texture and surface state to render this geometry
11288         surface.texture = texture;
11289         surface.num_triangles = numtriangles;
11290         surface.num_firsttriangle = firsttriangle;
11291         surface.num_vertices = numvertices;
11292         surface.num_firstvertex = firstvertex;
11293
11294         // now render it
11295         rsurface.texture = R_GetCurrentTexture(surface.texture);
11296         rsurface.lightmaptexture = NULL;
11297         rsurface.deluxemaptexture = NULL;
11298         rsurface.uselightmaptexture = false;
11299         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11300 }