]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix flipped scissor coordinates in dpsoftrast render path
[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_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 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"};
121
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130
131 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)"};
132 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"};
133
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 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)"};
145 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
146 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)"};
147 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
148 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)"};
149 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
150 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158 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)"};
159
160 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)"};
161 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
162 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"};
163 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
164 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
165 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
166
167 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
168 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
169 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
170 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
171
172 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
173 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
174 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
175 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
176 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
177 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
178 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
179
180 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
181 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
182 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
183 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)"};
184 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
185 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
186 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
188 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
189 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
190
191 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"};
192
193 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"};
194
195 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
196
197 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
198 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"};
199 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
200 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
201 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
202 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
203 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)"};
204 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
205 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
206
207 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
208 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"};
209
210 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
211
212 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)"};
213
214 extern cvar_t v_glslgamma;
215
216 extern qboolean v_flipped_state;
217
218 static struct r_bloomstate_s
219 {
220         qboolean enabled;
221         qboolean hdr;
222
223         int bloomwidth, bloomheight;
224
225         int screentexturewidth, screentextureheight;
226         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
227
228         int bloomtexturewidth, bloomtextureheight;
229         rtexture_t *texture_bloom;
230
231         // arrays for rendering the screen passes
232         float screentexcoord2f[8];
233         float bloomtexcoord2f[8];
234         float offsettexcoord2f[8];
235
236         r_viewport_t viewport;
237 }
238 r_bloomstate;
239
240 r_waterstate_t r_waterstate;
241
242 /// shadow volume bsp struct with automatically growing nodes buffer
243 svbsp_t r_svbsp;
244
245 rtexture_t *r_texture_blanknormalmap;
246 rtexture_t *r_texture_white;
247 rtexture_t *r_texture_grey128;
248 rtexture_t *r_texture_black;
249 rtexture_t *r_texture_notexture;
250 rtexture_t *r_texture_whitecube;
251 rtexture_t *r_texture_normalizationcube;
252 rtexture_t *r_texture_fogattenuation;
253 rtexture_t *r_texture_fogheighttexture;
254 rtexture_t *r_texture_gammaramps;
255 unsigned int r_texture_gammaramps_serial;
256 //rtexture_t *r_texture_fogintensity;
257 rtexture_t *r_texture_reflectcube;
258
259 // TODO: hash lookups?
260 typedef struct cubemapinfo_s
261 {
262         char basename[64];
263         rtexture_t *texture;
264 }
265 cubemapinfo_t;
266
267 int r_texture_numcubemaps;
268 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
269
270 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
271 unsigned int r_numqueries;
272 unsigned int r_maxqueries;
273
274 typedef struct r_qwskincache_s
275 {
276         char name[MAX_QPATH];
277         skinframe_t *skinframe;
278 }
279 r_qwskincache_t;
280
281 static r_qwskincache_t *r_qwskincache;
282 static int r_qwskincache_size;
283
284 /// vertex coordinates for a quad that covers the screen exactly
285 extern const float r_screenvertex3f[12];
286 extern const float r_d3dscreenvertex3f[12];
287 const float r_screenvertex3f[12] =
288 {
289         0, 0, 0,
290         1, 0, 0,
291         1, 1, 0,
292         0, 1, 0
293 };
294 const float r_d3dscreenvertex3f[12] =
295 {
296         0, 1, 0,
297         1, 1, 0,
298         1, 0, 0,
299         0, 0, 0
300 };
301
302 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
303 {
304         int i;
305         for (i = 0;i < verts;i++)
306         {
307                 out[0] = in[0] * r;
308                 out[1] = in[1] * g;
309                 out[2] = in[2] * b;
310                 out[3] = in[3];
311                 in += 4;
312                 out += 4;
313         }
314 }
315
316 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
317 {
318         int i;
319         for (i = 0;i < verts;i++)
320         {
321                 out[0] = r;
322                 out[1] = g;
323                 out[2] = b;
324                 out[3] = a;
325                 out += 4;
326         }
327 }
328
329 // FIXME: move this to client?
330 void FOG_clear(void)
331 {
332         if (gamemode == GAME_NEHAHRA)
333         {
334                 Cvar_Set("gl_fogenable", "0");
335                 Cvar_Set("gl_fogdensity", "0.2");
336                 Cvar_Set("gl_fogred", "0.3");
337                 Cvar_Set("gl_foggreen", "0.3");
338                 Cvar_Set("gl_fogblue", "0.3");
339         }
340         r_refdef.fog_density = 0;
341         r_refdef.fog_red = 0;
342         r_refdef.fog_green = 0;
343         r_refdef.fog_blue = 0;
344         r_refdef.fog_alpha = 1;
345         r_refdef.fog_start = 0;
346         r_refdef.fog_end = 16384;
347         r_refdef.fog_height = 1<<30;
348         r_refdef.fog_fadedepth = 128;
349         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
350 }
351
352 static void R_BuildBlankTextures(void)
353 {
354         unsigned char data[4];
355         data[2] = 128; // normal X
356         data[1] = 128; // normal Y
357         data[0] = 255; // normal Z
358         data[3] = 128; // height
359         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 255;
361         data[1] = 255;
362         data[2] = 255;
363         data[3] = 255;
364         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 128;
366         data[1] = 128;
367         data[2] = 128;
368         data[3] = 255;
369         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 0;
371         data[1] = 0;
372         data[2] = 0;
373         data[3] = 255;
374         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375 }
376
377 static void R_BuildNoTexture(void)
378 {
379         int x, y;
380         unsigned char pix[16][16][4];
381         // this makes a light grey/dark grey checkerboard texture
382         for (y = 0;y < 16;y++)
383         {
384                 for (x = 0;x < 16;x++)
385                 {
386                         if ((y < 8) ^ (x < 8))
387                         {
388                                 pix[y][x][0] = 128;
389                                 pix[y][x][1] = 128;
390                                 pix[y][x][2] = 128;
391                                 pix[y][x][3] = 255;
392                         }
393                         else
394                         {
395                                 pix[y][x][0] = 64;
396                                 pix[y][x][1] = 64;
397                                 pix[y][x][2] = 64;
398                                 pix[y][x][3] = 255;
399                         }
400                 }
401         }
402         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildWhiteCube(void)
406 {
407         unsigned char data[6*1*1*4];
408         memset(data, 255, sizeof(data));
409         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
410 }
411
412 static void R_BuildNormalizationCube(void)
413 {
414         int x, y, side;
415         vec3_t v;
416         vec_t s, t, intensity;
417 #define NORMSIZE 64
418         unsigned char *data;
419         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
420         for (side = 0;side < 6;side++)
421         {
422                 for (y = 0;y < NORMSIZE;y++)
423                 {
424                         for (x = 0;x < NORMSIZE;x++)
425                         {
426                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
428                                 switch(side)
429                                 {
430                                 default:
431                                 case 0:
432                                         v[0] = 1;
433                                         v[1] = -t;
434                                         v[2] = -s;
435                                         break;
436                                 case 1:
437                                         v[0] = -1;
438                                         v[1] = -t;
439                                         v[2] = s;
440                                         break;
441                                 case 2:
442                                         v[0] = s;
443                                         v[1] = 1;
444                                         v[2] = t;
445                                         break;
446                                 case 3:
447                                         v[0] = s;
448                                         v[1] = -1;
449                                         v[2] = -t;
450                                         break;
451                                 case 4:
452                                         v[0] = s;
453                                         v[1] = -t;
454                                         v[2] = 1;
455                                         break;
456                                 case 5:
457                                         v[0] = -s;
458                                         v[1] = -t;
459                                         v[2] = -1;
460                                         break;
461                                 }
462                                 intensity = 127.0f / sqrt(DotProduct(v, v));
463                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
464                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
465                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
466                                 data[((side*64+y)*64+x)*4+3] = 255;
467                         }
468                 }
469         }
470         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
471         Mem_Free(data);
472 }
473
474 static void R_BuildFogTexture(void)
475 {
476         int x, b;
477 #define FOGWIDTH 256
478         unsigned char data1[FOGWIDTH][4];
479         //unsigned char data2[FOGWIDTH][4];
480         double d, r, alpha;
481
482         r_refdef.fogmasktable_start = r_refdef.fog_start;
483         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
484         r_refdef.fogmasktable_range = r_refdef.fogrange;
485         r_refdef.fogmasktable_density = r_refdef.fog_density;
486
487         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
488         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
489         {
490                 d = (x * r - r_refdef.fogmasktable_start);
491                 if(developer_extra.integer)
492                         Con_DPrintf("%f ", d);
493                 d = max(0, d);
494                 if (r_fog_exp2.integer)
495                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
496                 else
497                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
498                 if(developer_extra.integer)
499                         Con_DPrintf(" : %f ", alpha);
500                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
501                 if(developer_extra.integer)
502                         Con_DPrintf(" = %f\n", alpha);
503                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
504         }
505
506         for (x = 0;x < FOGWIDTH;x++)
507         {
508                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
509                 data1[x][0] = b;
510                 data1[x][1] = b;
511                 data1[x][2] = b;
512                 data1[x][3] = 255;
513                 //data2[x][0] = 255 - b;
514                 //data2[x][1] = 255 - b;
515                 //data2[x][2] = 255 - b;
516                 //data2[x][3] = 255;
517         }
518         if (r_texture_fogattenuation)
519         {
520                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
522         }
523         else
524         {
525                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
526                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
527         }
528 }
529
530 static void R_BuildFogHeightTexture(void)
531 {
532         unsigned char *inpixels;
533         int size;
534         int x;
535         int y;
536         int j;
537         float c[4];
538         float f;
539         inpixels = NULL;
540         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
541         if (r_refdef.fogheighttexturename[0])
542                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
543         if (!inpixels)
544         {
545                 r_refdef.fog_height_tablesize = 0;
546                 if (r_texture_fogheighttexture)
547                         R_FreeTexture(r_texture_fogheighttexture);
548                 r_texture_fogheighttexture = NULL;
549                 if (r_refdef.fog_height_table2d)
550                         Mem_Free(r_refdef.fog_height_table2d);
551                 r_refdef.fog_height_table2d = NULL;
552                 if (r_refdef.fog_height_table1d)
553                         Mem_Free(r_refdef.fog_height_table1d);
554                 r_refdef.fog_height_table1d = NULL;
555                 return;
556         }
557         size = image_width;
558         r_refdef.fog_height_tablesize = size;
559         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
560         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
561         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
562         Mem_Free(inpixels);
563         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
564         // average fog color table accounting for every fog layer between a point
565         // and the camera.  (Note: attenuation is handled separately!)
566         for (y = 0;y < size;y++)
567         {
568                 for (x = 0;x < size;x++)
569                 {
570                         Vector4Clear(c);
571                         f = 0;
572                         if (x < y)
573                         {
574                                 for (j = x;j <= y;j++)
575                                 {
576                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577                                         f++;
578                                 }
579                         }
580                         else
581                         {
582                                 for (j = x;j >= y;j--)
583                                 {
584                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
585                                         f++;
586                                 }
587                         }
588                         f = 1.0f / f;
589                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
591                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
592                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
593                 }
594         }
595         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
596 }
597
598 //=======================================================================================================================================================
599
600 static const char *builtinshaderstring =
601 #include "shader_glsl.h"
602 ;
603
604 const char *builtinhlslshaderstring =
605 #include "shader_hlsl.h"
606 ;
607
608 char *glslshaderstring = NULL;
609 char *hlslshaderstring = NULL;
610
611 //=======================================================================================================================================================
612
613 typedef struct shaderpermutationinfo_s
614 {
615         const char *pretext;
616         const char *name;
617 }
618 shaderpermutationinfo_t;
619
620 typedef struct shadermodeinfo_s
621 {
622         const char *vertexfilename;
623         const char *geometryfilename;
624         const char *fragmentfilename;
625         const char *pretext;
626         const char *name;
627 }
628 shadermodeinfo_t;
629
630 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
631 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
632 {
633         {"#define USEDIFFUSE\n", " diffuse"},
634         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
635         {"#define USEVIEWTINT\n", " viewtint"},
636         {"#define USECOLORMAPPING\n", " colormapping"},
637         {"#define USESATURATION\n", " saturation"},
638         {"#define USEFOGINSIDE\n", " foginside"},
639         {"#define USEFOGOUTSIDE\n", " fogoutside"},
640         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
641         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
642         {"#define USEGAMMARAMPS\n", " gammaramps"},
643         {"#define USECUBEFILTER\n", " cubefilter"},
644         {"#define USEGLOW\n", " glow"},
645         {"#define USEBLOOM\n", " bloom"},
646         {"#define USESPECULAR\n", " specular"},
647         {"#define USEPOSTPROCESSING\n", " postprocessing"},
648         {"#define USEREFLECTION\n", " reflection"},
649         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
650         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
651         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
652         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
653         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
654         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
655         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
656         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
657         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
658         {"#define USEALPHAKILL\n", " alphakill"},
659         {"#define USEREFLECTCUBE\n", " reflectcube"},
660         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
661         {"#define USEBOUNCEGRID\n", " bouncegrid"},
662         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
663 };
664
665 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
666 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
667 {
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
670         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
684 };
685
686 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 struct r_glsl_permutation_s;
707 typedef struct r_glsl_permutation_s
708 {
709         /// hash lookup data
710         struct r_glsl_permutation_s *hashnext;
711         unsigned int mode;
712         unsigned int permutation;
713
714         /// indicates if we have tried compiling this permutation already
715         qboolean compiled;
716         /// 0 if compilation failed
717         int program;
718         // texture units assigned to each detected uniform
719         int tex_Texture_First;
720         int tex_Texture_Second;
721         int tex_Texture_GammaRamps;
722         int tex_Texture_Normal;
723         int tex_Texture_Color;
724         int tex_Texture_Gloss;
725         int tex_Texture_Glow;
726         int tex_Texture_SecondaryNormal;
727         int tex_Texture_SecondaryColor;
728         int tex_Texture_SecondaryGloss;
729         int tex_Texture_SecondaryGlow;
730         int tex_Texture_Pants;
731         int tex_Texture_Shirt;
732         int tex_Texture_FogHeightTexture;
733         int tex_Texture_FogMask;
734         int tex_Texture_Lightmap;
735         int tex_Texture_Deluxemap;
736         int tex_Texture_Attenuation;
737         int tex_Texture_Cube;
738         int tex_Texture_Refraction;
739         int tex_Texture_Reflection;
740         int tex_Texture_ShadowMap2D;
741         int tex_Texture_CubeProjection;
742         int tex_Texture_ScreenDepth;
743         int tex_Texture_ScreenNormalMap;
744         int tex_Texture_ScreenDiffuse;
745         int tex_Texture_ScreenSpecular;
746         int tex_Texture_ReflectMask;
747         int tex_Texture_ReflectCube;
748         int tex_Texture_BounceGrid;
749         /// locations of detected uniforms in program object, or -1 if not found
750         int loc_Texture_First;
751         int loc_Texture_Second;
752         int loc_Texture_GammaRamps;
753         int loc_Texture_Normal;
754         int loc_Texture_Color;
755         int loc_Texture_Gloss;
756         int loc_Texture_Glow;
757         int loc_Texture_SecondaryNormal;
758         int loc_Texture_SecondaryColor;
759         int loc_Texture_SecondaryGloss;
760         int loc_Texture_SecondaryGlow;
761         int loc_Texture_Pants;
762         int loc_Texture_Shirt;
763         int loc_Texture_FogHeightTexture;
764         int loc_Texture_FogMask;
765         int loc_Texture_Lightmap;
766         int loc_Texture_Deluxemap;
767         int loc_Texture_Attenuation;
768         int loc_Texture_Cube;
769         int loc_Texture_Refraction;
770         int loc_Texture_Reflection;
771         int loc_Texture_ShadowMap2D;
772         int loc_Texture_CubeProjection;
773         int loc_Texture_ScreenDepth;
774         int loc_Texture_ScreenNormalMap;
775         int loc_Texture_ScreenDiffuse;
776         int loc_Texture_ScreenSpecular;
777         int loc_Texture_ReflectMask;
778         int loc_Texture_ReflectCube;
779         int loc_Texture_BounceGrid;
780         int loc_Alpha;
781         int loc_BloomBlur_Parameters;
782         int loc_ClientTime;
783         int loc_Color_Ambient;
784         int loc_Color_Diffuse;
785         int loc_Color_Specular;
786         int loc_Color_Glow;
787         int loc_Color_Pants;
788         int loc_Color_Shirt;
789         int loc_DeferredColor_Ambient;
790         int loc_DeferredColor_Diffuse;
791         int loc_DeferredColor_Specular;
792         int loc_DeferredMod_Diffuse;
793         int loc_DeferredMod_Specular;
794         int loc_DistortScaleRefractReflect;
795         int loc_EyePosition;
796         int loc_FogColor;
797         int loc_FogHeightFade;
798         int loc_FogPlane;
799         int loc_FogPlaneViewDist;
800         int loc_FogRangeRecip;
801         int loc_LightColor;
802         int loc_LightDir;
803         int loc_LightPosition;
804         int loc_OffsetMapping_ScaleSteps;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
852 };
853 #define SHADERSTATICPARMS_COUNT 7
854
855 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
856 static int shaderstaticparms_count = 0;
857
858 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
859 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
860 qboolean R_CompileShader_CheckStaticParms(void)
861 {
862         static int r_compileshader_staticparms_save[1];
863         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
864         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
865
866         // detect all
867         if (r_glsl_saturation_redcompensate.integer)
868                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
869         if (r_glsl_vertextextureblend_usebothalphas.integer)
870                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
871         if (r_shadow_glossexact.integer)
872                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
873         if (r_glsl_postprocess.integer)
874         {
875                 if (r_glsl_postprocess_uservec1_enable.integer)
876                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
877                 if (r_glsl_postprocess_uservec2_enable.integer)
878                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
879                 if (r_glsl_postprocess_uservec3_enable.integer)
880                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
881                 if (r_glsl_postprocess_uservec4_enable.integer)
882                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
883         }
884         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
885 }
886
887 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
888         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
889                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
890         else \
891                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
892 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
893 {
894         shaderstaticparms_count = 0;
895
896         // emit all
897         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
898         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
899         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
904 }
905
906 /// information about each possible shader permutation
907 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
908 /// currently selected permutation
909 r_glsl_permutation_t *r_glsl_permutation;
910 /// storage for permutations linked in the hash table
911 memexpandablearray_t r_glsl_permutationarray;
912
913 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
914 {
915         //unsigned int hashdepth = 0;
916         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
917         r_glsl_permutation_t *p;
918         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
919         {
920                 if (p->mode == mode && p->permutation == permutation)
921                 {
922                         //if (hashdepth > 10)
923                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
924                         return p;
925                 }
926                 //hashdepth++;
927         }
928         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
929         p->mode = mode;
930         p->permutation = permutation;
931         p->hashnext = r_glsl_permutationhash[mode][hashindex];
932         r_glsl_permutationhash[mode][hashindex] = p;
933         //if (hashdepth > 10)
934         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
935         return p;
936 }
937
938 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
939 {
940         char *shaderstring;
941         if (!filename || !filename[0])
942                 return NULL;
943         if (!strcmp(filename, "glsl/default.glsl"))
944         {
945                 if (!glslshaderstring)
946                 {
947                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
948                         if (glslshaderstring)
949                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
950                         else
951                                 glslshaderstring = (char *)builtinshaderstring;
952                 }
953                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
954                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
955                 return shaderstring;
956         }
957         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
958         if (shaderstring)
959         {
960                 if (printfromdisknotice)
961                         Con_DPrintf("from disk %s... ", filename);
962                 return shaderstring;
963         }
964         return shaderstring;
965 }
966
967 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
968 {
969         int i;
970         int sampler;
971         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
972         char *vertexstring, *geometrystring, *fragmentstring;
973         char permutationname[256];
974         int vertstrings_count = 0;
975         int geomstrings_count = 0;
976         int fragstrings_count = 0;
977         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
978         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
979         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
980
981         if (p->compiled)
982                 return;
983         p->compiled = true;
984         p->program = 0;
985
986         permutationname[0] = 0;
987         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
988         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
989         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
990
991         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
992
993         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
994         if(vid.support.gl20shaders130)
995         {
996                 vertstrings_list[vertstrings_count++] = "#version 130\n";
997                 geomstrings_list[geomstrings_count++] = "#version 130\n";
998                 fragstrings_list[fragstrings_count++] = "#version 130\n";
999                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1000                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1001                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1002         }
1003
1004         // the first pretext is which type of shader to compile as
1005         // (later these will all be bound together as a program object)
1006         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1007         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1008         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1009
1010         // the second pretext is the mode (for example a light source)
1011         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1012         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1013         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1014         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1015
1016         // now add all the permutation pretexts
1017         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1018         {
1019                 if (permutation & (1<<i))
1020                 {
1021                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1022                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1023                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1024                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1025                 }
1026                 else
1027                 {
1028                         // keep line numbers correct
1029                         vertstrings_list[vertstrings_count++] = "\n";
1030                         geomstrings_list[geomstrings_count++] = "\n";
1031                         fragstrings_list[fragstrings_count++] = "\n";
1032                 }
1033         }
1034
1035         // add static parms
1036         R_CompileShader_AddStaticParms(mode, permutation);
1037         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1038         vertstrings_count += shaderstaticparms_count;
1039         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1040         geomstrings_count += shaderstaticparms_count;
1041         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         fragstrings_count += shaderstaticparms_count;
1043
1044         // now append the shader text itself
1045         vertstrings_list[vertstrings_count++] = vertexstring;
1046         geomstrings_list[geomstrings_count++] = geometrystring;
1047         fragstrings_list[fragstrings_count++] = fragmentstring;
1048
1049         // if any sources were NULL, clear the respective list
1050         if (!vertexstring)
1051                 vertstrings_count = 0;
1052         if (!geometrystring)
1053                 geomstrings_count = 0;
1054         if (!fragmentstring)
1055                 fragstrings_count = 0;
1056
1057         // compile the shader program
1058         if (vertstrings_count + geomstrings_count + fragstrings_count)
1059                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1060         if (p->program)
1061         {
1062                 CHECKGLERROR
1063                 qglUseProgram(p->program);CHECKGLERROR
1064                 // look up all the uniform variable names we care about, so we don't
1065                 // have to look them up every time we set them
1066
1067                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1068                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1069                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1070                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1071                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1072                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1073                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1074                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1075                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1076                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1077                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1078                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1079                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1080                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1081                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1082                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1083                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1084                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1085                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1086                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1087                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1088                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1089                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1090                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1091                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1092                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1093                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1094                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1095                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1096                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1097                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1098                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1099                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1100                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1101                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1102                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1103                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1104                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1105                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1106                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1107                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1108                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1109                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1110                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1111                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1112                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1113                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1114                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1115                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1116                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1117                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1118                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1119                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1120                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1121                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1122                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1123                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1124                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1125                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1126                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1127                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1128                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1129                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1130                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1131                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1132                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1133                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1134                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1135                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1136                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1137                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1138                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1139                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1140                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1141                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1142                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1143                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1144                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1145                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1146                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1147                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1148                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1149                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1150                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1151                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1152                 // initialize the samplers to refer to the texture units we use
1153                 p->tex_Texture_First = -1;
1154                 p->tex_Texture_Second = -1;
1155                 p->tex_Texture_GammaRamps = -1;
1156                 p->tex_Texture_Normal = -1;
1157                 p->tex_Texture_Color = -1;
1158                 p->tex_Texture_Gloss = -1;
1159                 p->tex_Texture_Glow = -1;
1160                 p->tex_Texture_SecondaryNormal = -1;
1161                 p->tex_Texture_SecondaryColor = -1;
1162                 p->tex_Texture_SecondaryGloss = -1;
1163                 p->tex_Texture_SecondaryGlow = -1;
1164                 p->tex_Texture_Pants = -1;
1165                 p->tex_Texture_Shirt = -1;
1166                 p->tex_Texture_FogHeightTexture = -1;
1167                 p->tex_Texture_FogMask = -1;
1168                 p->tex_Texture_Lightmap = -1;
1169                 p->tex_Texture_Deluxemap = -1;
1170                 p->tex_Texture_Attenuation = -1;
1171                 p->tex_Texture_Cube = -1;
1172                 p->tex_Texture_Refraction = -1;
1173                 p->tex_Texture_Reflection = -1;
1174                 p->tex_Texture_ShadowMap2D = -1;
1175                 p->tex_Texture_CubeProjection = -1;
1176                 p->tex_Texture_ScreenDepth = -1;
1177                 p->tex_Texture_ScreenNormalMap = -1;
1178                 p->tex_Texture_ScreenDiffuse = -1;
1179                 p->tex_Texture_ScreenSpecular = -1;
1180                 p->tex_Texture_ReflectMask = -1;
1181                 p->tex_Texture_ReflectCube = -1;
1182                 p->tex_Texture_BounceGrid = -1;
1183                 sampler = 0;
1184                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1185                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1186                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1187                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1188                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1189                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1190                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1191                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1192                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1193                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1194                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1195                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1196                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1197                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1198                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1199                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1200                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1201                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1202                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1203                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1204                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1205                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1206                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1207                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1208                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1209                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1210                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1211                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1212                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1213                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1214                 CHECKGLERROR
1215                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1216         }
1217         else
1218                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1219
1220         // free the strings
1221         if (vertexstring)
1222                 Mem_Free(vertexstring);
1223         if (geometrystring)
1224                 Mem_Free(geometrystring);
1225         if (fragmentstring)
1226                 Mem_Free(fragmentstring);
1227 }
1228
1229 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1230 {
1231         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1232         if (r_glsl_permutation != perm)
1233         {
1234                 r_glsl_permutation = perm;
1235                 if (!r_glsl_permutation->program)
1236                 {
1237                         if (!r_glsl_permutation->compiled)
1238                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1239                         if (!r_glsl_permutation->program)
1240                         {
1241                                 // remove features until we find a valid permutation
1242                                 int i;
1243                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1244                                 {
1245                                         // reduce i more quickly whenever it would not remove any bits
1246                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1247                                         if (!(permutation & j))
1248                                                 continue;
1249                                         permutation -= j;
1250                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1251                                         if (!r_glsl_permutation->compiled)
1252                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1253                                         if (r_glsl_permutation->program)
1254                                                 break;
1255                                 }
1256                                 if (i >= SHADERPERMUTATION_COUNT)
1257                                 {
1258                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1259                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1260                                         qglUseProgram(0);CHECKGLERROR
1261                                         return; // no bit left to clear, entire mode is broken
1262                                 }
1263                         }
1264                 }
1265                 CHECKGLERROR
1266                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1267         }
1268         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1269         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1270         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1271 }
1272
1273 #ifdef SUPPORTD3D
1274
1275 #ifdef SUPPORTD3D
1276 #include <d3d9.h>
1277 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1278 extern D3DCAPS9 vid_d3d9caps;
1279 #endif
1280
1281 struct r_hlsl_permutation_s;
1282 typedef struct r_hlsl_permutation_s
1283 {
1284         /// hash lookup data
1285         struct r_hlsl_permutation_s *hashnext;
1286         unsigned int mode;
1287         unsigned int permutation;
1288
1289         /// indicates if we have tried compiling this permutation already
1290         qboolean compiled;
1291         /// NULL if compilation failed
1292         IDirect3DVertexShader9 *vertexshader;
1293         IDirect3DPixelShader9 *pixelshader;
1294 }
1295 r_hlsl_permutation_t;
1296
1297 typedef enum D3DVSREGISTER_e
1298 {
1299         D3DVSREGISTER_TexMatrix = 0, // float4x4
1300         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1301         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1302         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1303         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1304         D3DVSREGISTER_ModelToLight = 20, // float4x4
1305         D3DVSREGISTER_EyePosition = 24,
1306         D3DVSREGISTER_FogPlane = 25,
1307         D3DVSREGISTER_LightDir = 26,
1308         D3DVSREGISTER_LightPosition = 27,
1309 }
1310 D3DVSREGISTER_t;
1311
1312 typedef enum D3DPSREGISTER_e
1313 {
1314         D3DPSREGISTER_Alpha = 0,
1315         D3DPSREGISTER_BloomBlur_Parameters = 1,
1316         D3DPSREGISTER_ClientTime = 2,
1317         D3DPSREGISTER_Color_Ambient = 3,
1318         D3DPSREGISTER_Color_Diffuse = 4,
1319         D3DPSREGISTER_Color_Specular = 5,
1320         D3DPSREGISTER_Color_Glow = 6,
1321         D3DPSREGISTER_Color_Pants = 7,
1322         D3DPSREGISTER_Color_Shirt = 8,
1323         D3DPSREGISTER_DeferredColor_Ambient = 9,
1324         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1325         D3DPSREGISTER_DeferredColor_Specular = 11,
1326         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1327         D3DPSREGISTER_DeferredMod_Specular = 13,
1328         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1329         D3DPSREGISTER_EyePosition = 15, // unused
1330         D3DPSREGISTER_FogColor = 16,
1331         D3DPSREGISTER_FogHeightFade = 17,
1332         D3DPSREGISTER_FogPlane = 18,
1333         D3DPSREGISTER_FogPlaneViewDist = 19,
1334         D3DPSREGISTER_FogRangeRecip = 20,
1335         D3DPSREGISTER_LightColor = 21,
1336         D3DPSREGISTER_LightDir = 22, // unused
1337         D3DPSREGISTER_LightPosition = 23,
1338         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1339         D3DPSREGISTER_PixelSize = 25,
1340         D3DPSREGISTER_ReflectColor = 26,
1341         D3DPSREGISTER_ReflectFactor = 27,
1342         D3DPSREGISTER_ReflectOffset = 28,
1343         D3DPSREGISTER_RefractColor = 29,
1344         D3DPSREGISTER_Saturation = 30,
1345         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1346         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1347         D3DPSREGISTER_ScreenToDepth = 33,
1348         D3DPSREGISTER_ShadowMap_Parameters = 34,
1349         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1350         D3DPSREGISTER_SpecularPower = 36,
1351         D3DPSREGISTER_UserVec1 = 37,
1352         D3DPSREGISTER_UserVec2 = 38,
1353         D3DPSREGISTER_UserVec3 = 39,
1354         D3DPSREGISTER_UserVec4 = 40,
1355         D3DPSREGISTER_ViewTintColor = 41,
1356         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1357         D3DPSREGISTER_BloomColorSubtract = 43,
1358         D3DPSREGISTER_ViewToLight = 44, // float4x4
1359         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1360         D3DPSREGISTER_NormalmapScrollBlend = 52,
1361         // next at 53
1362 }
1363 D3DPSREGISTER_t;
1364
1365 /// information about each possible shader permutation
1366 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1367 /// currently selected permutation
1368 r_hlsl_permutation_t *r_hlsl_permutation;
1369 /// storage for permutations linked in the hash table
1370 memexpandablearray_t r_hlsl_permutationarray;
1371
1372 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1373 {
1374         //unsigned int hashdepth = 0;
1375         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1376         r_hlsl_permutation_t *p;
1377         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1378         {
1379                 if (p->mode == mode && p->permutation == permutation)
1380                 {
1381                         //if (hashdepth > 10)
1382                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1383                         return p;
1384                 }
1385                 //hashdepth++;
1386         }
1387         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1388         p->mode = mode;
1389         p->permutation = permutation;
1390         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1391         r_hlsl_permutationhash[mode][hashindex] = p;
1392         //if (hashdepth > 10)
1393         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1394         return p;
1395 }
1396
1397 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1398 {
1399         char *shaderstring;
1400         if (!filename || !filename[0])
1401                 return NULL;
1402         if (!strcmp(filename, "hlsl/default.hlsl"))
1403         {
1404                 if (!hlslshaderstring)
1405                 {
1406                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1407                         if (hlslshaderstring)
1408                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1409                         else
1410                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1411                 }
1412                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1413                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1414                 return shaderstring;
1415         }
1416         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1417         if (shaderstring)
1418         {
1419                 if (printfromdisknotice)
1420                         Con_DPrintf("from disk %s... ", filename);
1421                 return shaderstring;
1422         }
1423         return shaderstring;
1424 }
1425
1426 #include <d3dx9.h>
1427 //#include <d3dx9shader.h>
1428 //#include <d3dx9mesh.h>
1429
1430 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1431 {
1432         DWORD *vsbin = NULL;
1433         DWORD *psbin = NULL;
1434         fs_offset_t vsbinsize;
1435         fs_offset_t psbinsize;
1436 //      IDirect3DVertexShader9 *vs = NULL;
1437 //      IDirect3DPixelShader9 *ps = NULL;
1438         ID3DXBuffer *vslog = NULL;
1439         ID3DXBuffer *vsbuffer = NULL;
1440         ID3DXConstantTable *vsconstanttable = NULL;
1441         ID3DXBuffer *pslog = NULL;
1442         ID3DXBuffer *psbuffer = NULL;
1443         ID3DXConstantTable *psconstanttable = NULL;
1444         int vsresult = 0;
1445         int psresult = 0;
1446         char temp[MAX_INPUTLINE];
1447         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1448         qboolean debugshader = gl_paranoid.integer != 0;
1449         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1450         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1451         if (!debugshader)
1452         {
1453                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1454                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1455         }
1456         if ((!vsbin && vertstring) || (!psbin && fragstring))
1457         {
1458                 const char* dllnames_d3dx9 [] =
1459                 {
1460                         "d3dx9_43.dll",
1461                         "d3dx9_42.dll",
1462                         "d3dx9_41.dll",
1463                         "d3dx9_40.dll",
1464                         "d3dx9_39.dll",
1465                         "d3dx9_38.dll",
1466                         "d3dx9_37.dll",
1467                         "d3dx9_36.dll",
1468                         "d3dx9_35.dll",
1469                         "d3dx9_34.dll",
1470                         "d3dx9_33.dll",
1471                         "d3dx9_32.dll",
1472                         "d3dx9_31.dll",
1473                         "d3dx9_30.dll",
1474                         "d3dx9_29.dll",
1475                         "d3dx9_28.dll",
1476                         "d3dx9_27.dll",
1477                         "d3dx9_26.dll",
1478                         "d3dx9_25.dll",
1479                         "d3dx9_24.dll",
1480                         NULL
1481                 };
1482                 dllhandle_t d3dx9_dll = NULL;
1483                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1484                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1485                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1486                 dllfunction_t d3dx9_dllfuncs[] =
1487                 {
1488                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1489                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1490                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1491                         {NULL, NULL}
1492                 };
1493                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1494                 {
1495                         DWORD shaderflags = 0;
1496                         if (debugshader)
1497                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1498                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1499                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1500                         if (vertstring && vertstring[0])
1501                         {
1502                                 if (debugshader)
1503                                 {
1504 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1505 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1506                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1507                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1508                                 }
1509                                 else
1510                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1511                                 if (vsbuffer)
1512                                 {
1513                                         vsbinsize = vsbuffer->GetBufferSize();
1514                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1515                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1516                                         vsbuffer->Release();
1517                                 }
1518                                 if (vslog)
1519                                 {
1520                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1521                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1522                                         vslog->Release();
1523                                 }
1524                         }
1525                         if (fragstring && fragstring[0])
1526                         {
1527                                 if (debugshader)
1528                                 {
1529 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1530 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1531                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1532                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1533                                 }
1534                                 else
1535                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1536                                 if (psbuffer)
1537                                 {
1538                                         psbinsize = psbuffer->GetBufferSize();
1539                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1540                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1541                                         psbuffer->Release();
1542                                 }
1543                                 if (pslog)
1544                                 {
1545                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1546                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1547                                         pslog->Release();
1548                                 }
1549                         }
1550                         Sys_UnloadLibrary(&d3dx9_dll);
1551                 }
1552                 else
1553                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1554         }
1555         if (vsbin && psbin)
1556         {
1557                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1558                 if (FAILED(vsresult))
1559                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1560                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1561                 if (FAILED(psresult))
1562                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1563         }
1564         // free the shader data
1565         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1566         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1567 }
1568
1569 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1570 {
1571         int i;
1572         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1573         int vertstring_length = 0;
1574         int geomstring_length = 0;
1575         int fragstring_length = 0;
1576         char *t;
1577         char *vertexstring, *geometrystring, *fragmentstring;
1578         char *vertstring, *geomstring, *fragstring;
1579         char permutationname[256];
1580         char cachename[256];
1581         int vertstrings_count = 0;
1582         int geomstrings_count = 0;
1583         int fragstrings_count = 0;
1584         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1585         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1586         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1587
1588         if (p->compiled)
1589                 return;
1590         p->compiled = true;
1591         p->vertexshader = NULL;
1592         p->pixelshader = NULL;
1593
1594         permutationname[0] = 0;
1595         cachename[0] = 0;
1596         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1597         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1598         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1599
1600         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1601         strlcat(cachename, "hlsl/", sizeof(cachename));
1602
1603         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1604         vertstrings_count = 0;
1605         geomstrings_count = 0;
1606         fragstrings_count = 0;
1607         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1608         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1609         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1610
1611         // the first pretext is which type of shader to compile as
1612         // (later these will all be bound together as a program object)
1613         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1614         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1615         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1616
1617         // the second pretext is the mode (for example a light source)
1618         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1619         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1620         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1621         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1622         strlcat(cachename, modeinfo->name, sizeof(cachename));
1623
1624         // now add all the permutation pretexts
1625         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1626         {
1627                 if (permutation & (1<<i))
1628                 {
1629                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1630                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1631                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1632                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1633                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1634                 }
1635                 else
1636                 {
1637                         // keep line numbers correct
1638                         vertstrings_list[vertstrings_count++] = "\n";
1639                         geomstrings_list[geomstrings_count++] = "\n";
1640                         fragstrings_list[fragstrings_count++] = "\n";
1641                 }
1642         }
1643
1644         // add static parms
1645         R_CompileShader_AddStaticParms(mode, permutation);
1646         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1647         vertstrings_count += shaderstaticparms_count;
1648         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1649         geomstrings_count += shaderstaticparms_count;
1650         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1651         fragstrings_count += shaderstaticparms_count;
1652
1653         // replace spaces in the cachename with _ characters
1654         for (i = 0;cachename[i];i++)
1655                 if (cachename[i] == ' ')
1656                         cachename[i] = '_';
1657
1658         // now append the shader text itself
1659         vertstrings_list[vertstrings_count++] = vertexstring;
1660         geomstrings_list[geomstrings_count++] = geometrystring;
1661         fragstrings_list[fragstrings_count++] = fragmentstring;
1662
1663         // if any sources were NULL, clear the respective list
1664         if (!vertexstring)
1665                 vertstrings_count = 0;
1666         if (!geometrystring)
1667                 geomstrings_count = 0;
1668         if (!fragmentstring)
1669                 fragstrings_count = 0;
1670
1671         vertstring_length = 0;
1672         for (i = 0;i < vertstrings_count;i++)
1673                 vertstring_length += strlen(vertstrings_list[i]);
1674         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1675         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1676                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1677
1678         geomstring_length = 0;
1679         for (i = 0;i < geomstrings_count;i++)
1680                 geomstring_length += strlen(geomstrings_list[i]);
1681         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1682         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1683                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1684
1685         fragstring_length = 0;
1686         for (i = 0;i < fragstrings_count;i++)
1687                 fragstring_length += strlen(fragstrings_list[i]);
1688         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1689         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1690                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1691
1692         // try to load the cached shader, or generate one
1693         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1694
1695         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1696                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1697         else
1698                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1699
1700         // free the strings
1701         if (vertstring)
1702                 Mem_Free(vertstring);
1703         if (geomstring)
1704                 Mem_Free(geomstring);
1705         if (fragstring)
1706                 Mem_Free(fragstring);
1707         if (vertexstring)
1708                 Mem_Free(vertexstring);
1709         if (geometrystring)
1710                 Mem_Free(geometrystring);
1711         if (fragmentstring)
1712                 Mem_Free(fragmentstring);
1713 }
1714
1715 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1716 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1717 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);}
1718 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);}
1719 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);}
1720 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);}
1721
1722 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1723 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1724 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);}
1725 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);}
1726 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);}
1727 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);}
1728
1729 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1730 {
1731         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1732         if (r_hlsl_permutation != perm)
1733         {
1734                 r_hlsl_permutation = perm;
1735                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1736                 {
1737                         if (!r_hlsl_permutation->compiled)
1738                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1739                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1740                         {
1741                                 // remove features until we find a valid permutation
1742                                 int i;
1743                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1744                                 {
1745                                         // reduce i more quickly whenever it would not remove any bits
1746                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1747                                         if (!(permutation & j))
1748                                                 continue;
1749                                         permutation -= j;
1750                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1751                                         if (!r_hlsl_permutation->compiled)
1752                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1753                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1754                                                 break;
1755                                 }
1756                                 if (i >= SHADERPERMUTATION_COUNT)
1757                                 {
1758                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1759                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1760                                         return; // no bit left to clear, entire mode is broken
1761                                 }
1762                         }
1763                 }
1764                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1765                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1766         }
1767         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1768         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1769         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1770 }
1771 #endif
1772
1773 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1774 {
1775         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1776         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1777         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1778         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1779 }
1780
1781 void R_GLSL_Restart_f(void)
1782 {
1783         unsigned int i, limit;
1784         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1785                 Mem_Free(glslshaderstring);
1786         glslshaderstring = NULL;
1787         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1788                 Mem_Free(hlslshaderstring);
1789         hlslshaderstring = NULL;
1790         switch(vid.renderpath)
1791         {
1792         case RENDERPATH_D3D9:
1793 #ifdef SUPPORTD3D
1794                 {
1795                         r_hlsl_permutation_t *p;
1796                         r_hlsl_permutation = NULL;
1797                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1798                         for (i = 0;i < limit;i++)
1799                         {
1800                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1801                                 {
1802                                         if (p->vertexshader)
1803                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1804                                         if (p->pixelshader)
1805                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1806                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1807                                 }
1808                         }
1809                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1810                 }
1811 #endif
1812                 break;
1813         case RENDERPATH_D3D10:
1814                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1815                 break;
1816         case RENDERPATH_D3D11:
1817                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1818                 break;
1819         case RENDERPATH_GL20:
1820         case RENDERPATH_GLES2:
1821                 {
1822                         r_glsl_permutation_t *p;
1823                         r_glsl_permutation = NULL;
1824                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1825                         for (i = 0;i < limit;i++)
1826                         {
1827                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1828                                 {
1829                                         GL_Backend_FreeProgram(p->program);
1830                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1831                                 }
1832                         }
1833                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1834                 }
1835                 break;
1836         case RENDERPATH_GL13:
1837         case RENDERPATH_GL11:
1838                 break;
1839         case RENDERPATH_SOFT:
1840                 break;
1841         }
1842 }
1843
1844 void R_GLSL_DumpShader_f(void)
1845 {
1846         int i;
1847         qfile_t *file;
1848
1849         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1850         if (file)
1851         {
1852                 FS_Print(file, "/* The engine may define the following macros:\n");
1853                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1854                 for (i = 0;i < SHADERMODE_COUNT;i++)
1855                         FS_Print(file, glslshadermodeinfo[i].pretext);
1856                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1857                         FS_Print(file, shaderpermutationinfo[i].pretext);
1858                 FS_Print(file, "*/\n");
1859                 FS_Print(file, builtinshaderstring);
1860                 FS_Close(file);
1861                 Con_Printf("glsl/default.glsl written\n");
1862         }
1863         else
1864                 Con_Printf("failed to write to glsl/default.glsl\n");
1865
1866         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1867         if (file)
1868         {
1869                 FS_Print(file, "/* The engine may define the following macros:\n");
1870                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871                 for (i = 0;i < SHADERMODE_COUNT;i++)
1872                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1873                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874                         FS_Print(file, shaderpermutationinfo[i].pretext);
1875                 FS_Print(file, "*/\n");
1876                 FS_Print(file, builtinhlslshaderstring);
1877                 FS_Close(file);
1878                 Con_Printf("hlsl/default.hlsl written\n");
1879         }
1880         else
1881                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1882 }
1883
1884 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1885 {
1886         if (!second)
1887                 texturemode = GL_MODULATE;
1888         switch (vid.renderpath)
1889         {
1890         case RENDERPATH_D3D9:
1891 #ifdef SUPPORTD3D
1892                 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))));
1893                 R_Mesh_TexBind(GL20TU_FIRST , first );
1894                 R_Mesh_TexBind(GL20TU_SECOND, second);
1895 #endif
1896                 break;
1897         case RENDERPATH_D3D10:
1898                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1899                 break;
1900         case RENDERPATH_D3D11:
1901                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1902                 break;
1903         case RENDERPATH_GL20:
1904         case RENDERPATH_GLES2:
1905                 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))));
1906                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1907                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1908                 break;
1909         case RENDERPATH_GL13:
1910                 R_Mesh_TexBind(0, first );
1911                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1912                 R_Mesh_TexBind(1, second);
1913                 if (second)
1914                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1915                 break;
1916         case RENDERPATH_GL11:
1917                 R_Mesh_TexBind(0, first );
1918                 break;
1919         case RENDERPATH_SOFT:
1920                 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))));
1921                 R_Mesh_TexBind(GL20TU_FIRST , first );
1922                 R_Mesh_TexBind(GL20TU_SECOND, second);
1923                 break;
1924         }
1925 }
1926
1927 void R_SetupShader_DepthOrShadow(void)
1928 {
1929         switch (vid.renderpath)
1930         {
1931         case RENDERPATH_D3D9:
1932 #ifdef SUPPORTD3D
1933                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1934 #endif
1935                 break;
1936         case RENDERPATH_D3D10:
1937                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1938                 break;
1939         case RENDERPATH_D3D11:
1940                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1941                 break;
1942         case RENDERPATH_GL20:
1943         case RENDERPATH_GLES2:
1944                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1945                 break;
1946         case RENDERPATH_GL13:
1947                 R_Mesh_TexBind(0, 0);
1948                 R_Mesh_TexBind(1, 0);
1949                 break;
1950         case RENDERPATH_GL11:
1951                 R_Mesh_TexBind(0, 0);
1952                 break;
1953         case RENDERPATH_SOFT:
1954                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1955                 break;
1956         }
1957 }
1958
1959 void R_SetupShader_ShowDepth(void)
1960 {
1961         switch (vid.renderpath)
1962         {
1963         case RENDERPATH_D3D9:
1964 #ifdef SUPPORTHLSL
1965                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1966 #endif
1967                 break;
1968         case RENDERPATH_D3D10:
1969                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1970                 break;
1971         case RENDERPATH_D3D11:
1972                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1973                 break;
1974         case RENDERPATH_GL20:
1975         case RENDERPATH_GLES2:
1976                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1977                 break;
1978         case RENDERPATH_GL13:
1979                 break;
1980         case RENDERPATH_GL11:
1981                 break;
1982         case RENDERPATH_SOFT:
1983                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1984                 break;
1985         }
1986 }
1987
1988 extern qboolean r_shadow_usingdeferredprepass;
1989 extern cvar_t r_shadow_deferred_8bitrange;
1990 extern rtexture_t *r_shadow_attenuationgradienttexture;
1991 extern rtexture_t *r_shadow_attenuation2dtexture;
1992 extern rtexture_t *r_shadow_attenuation3dtexture;
1993 extern qboolean r_shadow_usingshadowmap2d;
1994 extern qboolean r_shadow_usingshadowmaportho;
1995 extern float r_shadow_shadowmap_texturescale[2];
1996 extern float r_shadow_shadowmap_parameters[4];
1997 extern qboolean r_shadow_shadowmapvsdct;
1998 extern qboolean r_shadow_shadowmapsampler;
1999 extern int r_shadow_shadowmappcf;
2000 extern rtexture_t *r_shadow_shadowmap2dtexture;
2001 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2002 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2003 extern matrix4x4_t r_shadow_shadowmapmatrix;
2004 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2005 extern int r_shadow_prepass_width;
2006 extern int r_shadow_prepass_height;
2007 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2008 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2009 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2010 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2011 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2012
2013 #define BLENDFUNC_ALLOWS_COLORMOD      1
2014 #define BLENDFUNC_ALLOWS_FOG           2
2015 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2016 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2017 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2018 static int R_BlendFuncFlags(int src, int dst)
2019 {
2020         int r = 0;
2021
2022         // a blendfunc allows colormod if:
2023         // a) it can never keep the destination pixel invariant, or
2024         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2025         // this is to prevent unintended side effects from colormod
2026
2027         // a blendfunc allows fog if:
2028         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2029         // this is to prevent unintended side effects from fog
2030
2031         // these checks are the output of fogeval.pl
2032
2033         r |= BLENDFUNC_ALLOWS_COLORMOD;
2034         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2036         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2037         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2038         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2041         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2042         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2043         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2044         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2045         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2046         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2047         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2048         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2049         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2052         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2053         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2054         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055
2056         return r;
2057 }
2058
2059 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)
2060 {
2061         // select a permutation of the lighting shader appropriate to this
2062         // combination of texture, entity, light source, and fogging, only use the
2063         // minimum features necessary to avoid wasting rendering time in the
2064         // fragment shader on features that are not being used
2065         unsigned int permutation = 0;
2066         unsigned int mode = 0;
2067         int blendfuncflags;
2068         static float dummy_colormod[3] = {1, 1, 1};
2069         float *colormod = rsurface.colormod;
2070         float m16f[16];
2071         matrix4x4_t tempmatrix;
2072         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2073         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2074                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2075         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2076                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2077         if (rsurfacepass == RSURFPASS_BACKGROUND)
2078         {
2079                 // distorted background
2080                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2081                 {
2082                         mode = SHADERMODE_WATER;
2083                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2084                         {
2085                                 // this is the right thing to do for wateralpha
2086                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2087                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2088                         }
2089                         else
2090                         {
2091                                 // this is the right thing to do for entity alpha
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                 }
2096                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2097                 {
2098                         mode = SHADERMODE_REFRACTION;
2099                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2100                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2101                 }
2102                 else
2103                 {
2104                         mode = SHADERMODE_GENERIC;
2105                         permutation |= SHADERPERMUTATION_DIFFUSE;
2106                         GL_BlendFunc(GL_ONE, GL_ZERO);
2107                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2108                 }
2109         }
2110         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2111         {
2112                 if (r_glsl_offsetmapping.integer)
2113                 {
2114                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2115                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2116                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2117                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2118                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2119                         {
2120                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2121                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2122                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2123                         }
2124                 }
2125                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2126                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2127                 // normalmap (deferred prepass), may use alpha test on diffuse
2128                 mode = SHADERMODE_DEFERREDGEOMETRY;
2129                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2130                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2131                 GL_BlendFunc(GL_ONE, GL_ZERO);
2132                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2133         }
2134         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2135         {
2136                 if (r_glsl_offsetmapping.integer)
2137                 {
2138                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2139                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2140                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2141                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2142                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2143                         {
2144                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2145                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2146                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2147                         }
2148                 }
2149                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2150                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2151                 // light source
2152                 mode = SHADERMODE_LIGHTSOURCE;
2153                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2154                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2155                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2156                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2157                 if (diffusescale > 0)
2158                         permutation |= SHADERPERMUTATION_DIFFUSE;
2159                 if (specularscale > 0)
2160                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2161                 if (r_refdef.fogenabled)
2162                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2163                 if (rsurface.texture->colormapping)
2164                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2165                 if (r_shadow_usingshadowmap2d)
2166                 {
2167                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2168                         if(r_shadow_shadowmapvsdct)
2169                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2170
2171                         if (r_shadow_shadowmapsampler)
2172                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2173                         if (r_shadow_shadowmappcf > 1)
2174                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2175                         else if (r_shadow_shadowmappcf)
2176                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2177                 }
2178                 if (rsurface.texture->reflectmasktexture)
2179                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2180                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2181                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2182         }
2183         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2184         {
2185                 if (r_glsl_offsetmapping.integer)
2186                 {
2187                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2188                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2189                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2190                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2191                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2192                         {
2193                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2194                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2195                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2196                         }
2197                 }
2198                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2199                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2200                 // unshaded geometry (fullbright or ambient model lighting)
2201                 mode = SHADERMODE_FLATCOLOR;
2202                 ambientscale = diffusescale = specularscale = 0;
2203                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2204                         permutation |= SHADERPERMUTATION_GLOW;
2205                 if (r_refdef.fogenabled)
2206                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2207                 if (rsurface.texture->colormapping)
2208                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2209                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2210                 {
2211                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2212                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2213
2214                         if (r_shadow_shadowmapsampler)
2215                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2216                         if (r_shadow_shadowmappcf > 1)
2217                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2218                         else if (r_shadow_shadowmappcf)
2219                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2220                 }
2221                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2222                         permutation |= SHADERPERMUTATION_REFLECTION;
2223                 if (rsurface.texture->reflectmasktexture)
2224                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2225                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2226                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2227         }
2228         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2229         {
2230                 if (r_glsl_offsetmapping.integer)
2231                 {
2232                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2233                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2234                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2235                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2236                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2237                         {
2238                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2239                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2240                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2241                         }
2242                 }
2243                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2244                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2245                 // directional model lighting
2246                 mode = SHADERMODE_LIGHTDIRECTION;
2247                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2248                         permutation |= SHADERPERMUTATION_GLOW;
2249                 permutation |= SHADERPERMUTATION_DIFFUSE;
2250                 if (specularscale > 0)
2251                         permutation |= SHADERPERMUTATION_SPECULAR;
2252                 if (r_refdef.fogenabled)
2253                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2254                 if (rsurface.texture->colormapping)
2255                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2256                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2257                 {
2258                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2259                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2260
2261                         if (r_shadow_shadowmapsampler)
2262                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2263                         if (r_shadow_shadowmappcf > 1)
2264                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2265                         else if (r_shadow_shadowmappcf)
2266                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2267                 }
2268                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2269                         permutation |= SHADERPERMUTATION_REFLECTION;
2270                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2271                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2272                 if (rsurface.texture->reflectmasktexture)
2273                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2274                 if (r_shadow_bouncegridtexture)
2275                 {
2276                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2277                         if (r_shadow_bouncegriddirectional)
2278                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2279                 }
2280                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2282         }
2283         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2284         {
2285                 if (r_glsl_offsetmapping.integer)
2286                 {
2287                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2288                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2289                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2290                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2291                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2292                         {
2293                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2294                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2295                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2296                         }
2297                 }
2298                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2299                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2300                 // ambient model lighting
2301                 mode = SHADERMODE_LIGHTDIRECTION;
2302                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2303                         permutation |= SHADERPERMUTATION_GLOW;
2304                 if (r_refdef.fogenabled)
2305                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2306                 if (rsurface.texture->colormapping)
2307                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2308                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2309                 {
2310                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2311                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2312
2313                         if (r_shadow_shadowmapsampler)
2314                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2315                         if (r_shadow_shadowmappcf > 1)
2316                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2317                         else if (r_shadow_shadowmappcf)
2318                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2319                 }
2320                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2321                         permutation |= SHADERPERMUTATION_REFLECTION;
2322                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2323                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2324                 if (rsurface.texture->reflectmasktexture)
2325                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2326                 if (r_shadow_bouncegridtexture)
2327                 {
2328                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2329                         if (r_shadow_bouncegriddirectional)
2330                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2331                 }
2332                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334         }
2335         else
2336         {
2337                 if (r_glsl_offsetmapping.integer)
2338                 {
2339                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2340                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2341                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2342                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2343                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2344                         {
2345                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2346                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2347                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2348                         }
2349                 }
2350                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2351                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2352                 // lightmapped wall
2353                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2354                         permutation |= SHADERPERMUTATION_GLOW;
2355                 if (r_refdef.fogenabled)
2356                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2357                 if (rsurface.texture->colormapping)
2358                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2359                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2360                 {
2361                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2362                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2363
2364                         if (r_shadow_shadowmapsampler)
2365                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2366                         if (r_shadow_shadowmappcf > 1)
2367                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2368                         else if (r_shadow_shadowmappcf)
2369                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2370                 }
2371                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2372                         permutation |= SHADERPERMUTATION_REFLECTION;
2373                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2374                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2375                 if (rsurface.texture->reflectmasktexture)
2376                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2377                 if (FAKELIGHT_ENABLED)
2378                 {
2379                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2380                         mode = SHADERMODE_FAKELIGHT;
2381                         permutation |= SHADERPERMUTATION_DIFFUSE;
2382                         if (specularscale > 0)
2383                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2384                 }
2385                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2386                 {
2387                         // deluxemapping (light direction texture)
2388                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2389                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2390                         else
2391                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2392                         permutation |= SHADERPERMUTATION_DIFFUSE;
2393                         if (specularscale > 0)
2394                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395                 }
2396                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2397                 {
2398                         // fake deluxemapping (uniform light direction in tangentspace)
2399                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2400                         permutation |= SHADERPERMUTATION_DIFFUSE;
2401                         if (specularscale > 0)
2402                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2403                 }
2404                 else if (rsurface.uselightmaptexture)
2405                 {
2406                         // ordinary lightmapping (q1bsp, q3bsp)
2407                         mode = SHADERMODE_LIGHTMAP;
2408                 }
2409                 else
2410                 {
2411                         // ordinary vertex coloring (q3bsp)
2412                         mode = SHADERMODE_VERTEXCOLOR;
2413                 }
2414                 if (r_shadow_bouncegridtexture)
2415                 {
2416                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2417                         if (r_shadow_bouncegriddirectional)
2418                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2419                 }
2420                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2422         }
2423         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2424                 colormod = dummy_colormod;
2425         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2426                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2427         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2428                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2429         switch(vid.renderpath)
2430         {
2431         case RENDERPATH_D3D9:
2432 #ifdef SUPPORTD3D
2433                 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);
2434                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2435                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2436                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2437                 if (mode == SHADERMODE_LIGHTSOURCE)
2438                 {
2439                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2440                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2441                 }
2442                 else
2443                 {
2444                         if (mode == SHADERMODE_LIGHTDIRECTION)
2445                         {
2446                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2447                         }
2448                 }
2449                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2450                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2451                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2452                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2453                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2454
2455                 if (mode == SHADERMODE_LIGHTSOURCE)
2456                 {
2457                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2458                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2459                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2460                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2461                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2462
2463                         // additive passes are only darkened by fog, not tinted
2464                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2465                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2466                 }
2467                 else
2468                 {
2469                         if (mode == SHADERMODE_FLATCOLOR)
2470                         {
2471                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2472                         }
2473                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2474                         {
2475                                 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]);
2476                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2477                                 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);
2478                                 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);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2482                         }
2483                         else
2484                         {
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490                         }
2491                         // additive passes are only darkened by fog, not tinted
2492                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2494                         else
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2496                         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);
2497                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2498                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2499                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2501                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2502                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2503                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2504                         if (mode == SHADERMODE_WATER)
2505                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2506                 }
2507                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2508                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2509                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2510                 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));
2511                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2512                 if (rsurface.texture->pantstexture)
2513                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2514                 else
2515                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2516                 if (rsurface.texture->shirttexture)
2517                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2518                 else
2519                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2520                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2521                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2522                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2523                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2524                 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));
2525                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2526                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2527
2528                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2529                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2530                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2531                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2532                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2533                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2534                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2535                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2536                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2537                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2538                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2539                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2540                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2541                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2542                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2543                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2544                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2545                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2546                 {
2547                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2548                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2549                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2550                 }
2551                 else
2552                 {
2553                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2554                 }
2555 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2556 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2557                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2558                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2559                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2560                 {
2561                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2562                         if (rsurface.rtlight)
2563                         {
2564                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2565                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2566                         }
2567                 }
2568 #endif
2569                 break;
2570         case RENDERPATH_D3D10:
2571                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2572                 break;
2573         case RENDERPATH_D3D11:
2574                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2575                 break;
2576         case RENDERPATH_GL20:
2577         case RENDERPATH_GLES2:
2578                 if (!vid.useinterleavedarrays)
2579                 {
2580                         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);
2581                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2582                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2583                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2584                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2585                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2586                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2587                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2588                 }
2589                 else
2590                 {
2591                         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);
2592                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2593                 }
2594                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2595                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2596                 if (mode == SHADERMODE_LIGHTSOURCE)
2597                 {
2598                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2599                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2600                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2601                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2602                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2603                         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);
2604         
2605                         // additive passes are only darkened by fog, not tinted
2606                         if (r_glsl_permutation->loc_FogColor >= 0)
2607                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2608                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2609                 }
2610                 else
2611                 {
2612                         if (mode == SHADERMODE_FLATCOLOR)
2613                         {
2614                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2615                         }
2616                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2617                         {
2618                                 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]);
2619                                 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]);
2620                                 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);
2621                                 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);
2622                                 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);
2623                                 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]);
2624                                 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]);
2625                         }
2626                         else
2627                         {
2628                                 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]);
2629                                 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]);
2630                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2631                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2632                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2633                         }
2634                         // additive passes are only darkened by fog, not tinted
2635                         if (r_glsl_permutation->loc_FogColor >= 0)
2636                         {
2637                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2638                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2639                                 else
2640                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2641                         }
2642                         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);
2643                         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]);
2644                         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]);
2645                         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]);
2646                         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]);
2647                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2648                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2649                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2650                         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]);
2651                 }
2652                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2653                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2654                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2655                 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]);
2656                 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]);
2657
2658                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2659                 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));
2660                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2661                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2662                 {
2663                         if (rsurface.texture->pantstexture)
2664                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2665                         else
2666                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2667                 }
2668                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2669                 {
2670                         if (rsurface.texture->shirttexture)
2671                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2672                         else
2673                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2674                 }
2675                 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]);
2676                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2677                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2678                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2679                 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));
2680                 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]);
2681                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2682                 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);}
2683                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2684
2685                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2686                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2687                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2688                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2689                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2690                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2691                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2692                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2693                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2694                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2695                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2696                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2697                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2698                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2699                 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);
2700                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2701                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2702                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2703                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2704                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2705                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2706                 {
2707                         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);
2708                         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);
2709                         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);
2710                 }
2711                 else
2712                 {
2713                         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);
2714                 }
2715                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2716                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2717                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2718                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2719                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2720                 {
2721                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2722                         if (rsurface.rtlight)
2723                         {
2724                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2725                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2726                         }
2727                 }
2728                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2729                 CHECKGLERROR
2730                 break;
2731         case RENDERPATH_GL13:
2732         case RENDERPATH_GL11:
2733                 break;
2734         case RENDERPATH_SOFT:
2735                 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);
2736                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2737                 R_SetupShader_SetPermutationSoft(mode, permutation);
2738                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2739                 if (mode == SHADERMODE_LIGHTSOURCE)
2740                 {
2741                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2742                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2743                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2744                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2745                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2746                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2747         
2748                         // additive passes are only darkened by fog, not tinted
2749                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2750                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2751                 }
2752                 else
2753                 {
2754                         if (mode == SHADERMODE_FLATCOLOR)
2755                         {
2756                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2757                         }
2758                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2759                         {
2760                                 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]);
2761                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2762                                 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);
2763                                 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);
2764                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2765                                 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]);
2766                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2767                         }
2768                         else
2769                         {
2770                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775                         }
2776                         // additive passes are only darkened by fog, not tinted
2777                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2778                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2779                         else
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2781                         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);
2782                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2783                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2784                         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]);
2785                         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]);
2786                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2787                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2788                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2789                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2790                 }
2791                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2792                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2793                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2794                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2795                 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]);
2796
2797                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2798                 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));
2799                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2800                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2801                 {
2802                         if (rsurface.texture->pantstexture)
2803                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2804                         else
2805                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2806                 }
2807                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2808                 {
2809                         if (rsurface.texture->shirttexture)
2810                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2811                         else
2812                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2813                 }
2814                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2815                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2816                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2817                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2818                 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));
2819                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2820                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2821
2822                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2823                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2824                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2825                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2826                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2827                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2828                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2829                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2830                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2831                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2832                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2833                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2834                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2835                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2836                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2837                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2838                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2839                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2840                 {
2841                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2842                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2843                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2844                 }
2845                 else
2846                 {
2847                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2848                 }
2849 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2850 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2851                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2852                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2853                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2854                 {
2855                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2856                         if (rsurface.rtlight)
2857                         {
2858                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2859                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2860                         }
2861                 }
2862                 break;
2863         }
2864 }
2865
2866 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2867 {
2868         // select a permutation of the lighting shader appropriate to this
2869         // combination of texture, entity, light source, and fogging, only use the
2870         // minimum features necessary to avoid wasting rendering time in the
2871         // fragment shader on features that are not being used
2872         unsigned int permutation = 0;
2873         unsigned int mode = 0;
2874         const float *lightcolorbase = rtlight->currentcolor;
2875         float ambientscale = rtlight->ambientscale;
2876         float diffusescale = rtlight->diffusescale;
2877         float specularscale = rtlight->specularscale;
2878         // this is the location of the light in view space
2879         vec3_t viewlightorigin;
2880         // this transforms from view space (camera) to light space (cubemap)
2881         matrix4x4_t viewtolight;
2882         matrix4x4_t lighttoview;
2883         float viewtolight16f[16];
2884         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2885         // light source
2886         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2887         if (rtlight->currentcubemap != r_texture_whitecube)
2888                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2889         if (diffusescale > 0)
2890                 permutation |= SHADERPERMUTATION_DIFFUSE;
2891         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2892                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2893         if (r_shadow_usingshadowmap2d)
2894         {
2895                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2896                 if (r_shadow_shadowmapvsdct)
2897                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2898
2899                 if (r_shadow_shadowmapsampler)
2900                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2901                 if (r_shadow_shadowmappcf > 1)
2902                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2903                 else if (r_shadow_shadowmappcf)
2904                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2905         }
2906         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2907         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2908         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2909         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2910         switch(vid.renderpath)
2911         {
2912         case RENDERPATH_D3D9:
2913 #ifdef SUPPORTD3D
2914                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2915                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2916                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2917                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2918                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2919                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2920                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2921                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2922                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2923                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2924                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2925
2926                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2927                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2928                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2929                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2930                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2931                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2932 #endif
2933                 break;
2934         case RENDERPATH_D3D10:
2935                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2936                 break;
2937         case RENDERPATH_D3D11:
2938                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2939                 break;
2940         case RENDERPATH_GL20:
2941         case RENDERPATH_GLES2:
2942                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2943                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2944                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2945                 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);
2946                 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);
2947                 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);
2948                 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]);
2949                 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]);
2950                 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));
2951                 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]);
2952                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2953
2954                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2955                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2956                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2957                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2958                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2959                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2960                 break;
2961         case RENDERPATH_GL13:
2962         case RENDERPATH_GL11:
2963                 break;
2964         case RENDERPATH_SOFT:
2965                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2966                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2967                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2968                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2969                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2970                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2971                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2972                 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]);
2973                 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));
2974                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2975                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2976
2977                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2978                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2979                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2980                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2981                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2982                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2983                 break;
2984         }
2985 }
2986
2987 #define SKINFRAME_HASH 1024
2988
2989 typedef struct
2990 {
2991         int loadsequence; // incremented each level change
2992         memexpandablearray_t array;
2993         skinframe_t *hash[SKINFRAME_HASH];
2994 }
2995 r_skinframe_t;
2996 r_skinframe_t r_skinframe;
2997
2998 void R_SkinFrame_PrepareForPurge(void)
2999 {
3000         r_skinframe.loadsequence++;
3001         // wrap it without hitting zero
3002         if (r_skinframe.loadsequence >= 200)
3003                 r_skinframe.loadsequence = 1;
3004 }
3005
3006 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3007 {
3008         if (!skinframe)
3009                 return;
3010         // mark the skinframe as used for the purging code
3011         skinframe->loadsequence = r_skinframe.loadsequence;
3012 }
3013
3014 void R_SkinFrame_Purge(void)
3015 {
3016         int i;
3017         skinframe_t *s;
3018         for (i = 0;i < SKINFRAME_HASH;i++)
3019         {
3020                 for (s = r_skinframe.hash[i];s;s = s->next)
3021                 {
3022                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3023                         {
3024                                 if (s->merged == s->base)
3025                                         s->merged = NULL;
3026                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3027                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3028                                 R_PurgeTexture(s->merged);s->merged = NULL;
3029                                 R_PurgeTexture(s->base  );s->base   = NULL;
3030                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3031                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3032                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3033                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3034                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3035                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3036                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3037                                 s->loadsequence = 0;
3038                         }
3039                 }
3040         }
3041 }
3042
3043 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3044         skinframe_t *item;
3045         char basename[MAX_QPATH];
3046
3047         Image_StripImageExtension(name, basename, sizeof(basename));
3048
3049         if( last == NULL ) {
3050                 int hashindex;
3051                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3052                 item = r_skinframe.hash[hashindex];
3053         } else {
3054                 item = last->next;
3055         }
3056
3057         // linearly search through the hash bucket
3058         for( ; item ; item = item->next ) {
3059                 if( !strcmp( item->basename, basename ) ) {
3060                         return item;
3061                 }
3062         }
3063         return NULL;
3064 }
3065
3066 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3067 {
3068         skinframe_t *item;
3069         int hashindex;
3070         char basename[MAX_QPATH];
3071
3072         Image_StripImageExtension(name, basename, sizeof(basename));
3073
3074         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3075         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3076                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3077                         break;
3078
3079         if (!item) {
3080                 rtexture_t *dyntexture;
3081                 // check whether its a dynamic texture
3082                 dyntexture = CL_GetDynTexture( basename );
3083                 if (!add && !dyntexture)
3084                         return NULL;
3085                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3086                 memset(item, 0, sizeof(*item));
3087                 strlcpy(item->basename, basename, sizeof(item->basename));
3088                 item->base = dyntexture; // either NULL or dyntexture handle
3089                 item->textureflags = textureflags;
3090                 item->comparewidth = comparewidth;
3091                 item->compareheight = compareheight;
3092                 item->comparecrc = comparecrc;
3093                 item->next = r_skinframe.hash[hashindex];
3094                 r_skinframe.hash[hashindex] = item;
3095         }
3096         else if( item->base == NULL )
3097         {
3098                 rtexture_t *dyntexture;
3099                 // check whether its a dynamic texture
3100                 // 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]
3101                 dyntexture = CL_GetDynTexture( basename );
3102                 item->base = dyntexture; // either NULL or dyntexture handle
3103         }
3104
3105         R_SkinFrame_MarkUsed(item);
3106         return item;
3107 }
3108
3109 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3110         { \
3111                 unsigned long long avgcolor[5], wsum; \
3112                 int pix, comp, w; \
3113                 avgcolor[0] = 0; \
3114                 avgcolor[1] = 0; \
3115                 avgcolor[2] = 0; \
3116                 avgcolor[3] = 0; \
3117                 avgcolor[4] = 0; \
3118                 wsum = 0; \
3119                 for(pix = 0; pix < cnt; ++pix) \
3120                 { \
3121                         w = 0; \
3122                         for(comp = 0; comp < 3; ++comp) \
3123                                 w += getpixel; \
3124                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3125                         { \
3126                                 ++wsum; \
3127                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3128                                 w = getpixel; \
3129                                 for(comp = 0; comp < 3; ++comp) \
3130                                         avgcolor[comp] += getpixel * w; \
3131                                 avgcolor[3] += w; \
3132                         } \
3133                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3134                         avgcolor[4] += getpixel; \
3135                 } \
3136                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3137                         avgcolor[3] = 1; \
3138                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3139                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3140                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3141                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3142         }
3143
3144 extern cvar_t gl_picmip;
3145 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3146 {
3147         int j;
3148         unsigned char *pixels;
3149         unsigned char *bumppixels;
3150         unsigned char *basepixels = NULL;
3151         int basepixels_width = 0;
3152         int basepixels_height = 0;
3153         skinframe_t *skinframe;
3154         rtexture_t *ddsbase = NULL;
3155         qboolean ddshasalpha = false;
3156         float ddsavgcolor[4];
3157         char basename[MAX_QPATH];
3158         int miplevel = R_PicmipForFlags(textureflags);
3159         int savemiplevel = miplevel;
3160         int mymiplevel;
3161
3162         if (cls.state == ca_dedicated)
3163                 return NULL;
3164
3165         // return an existing skinframe if already loaded
3166         // if loading of the first image fails, don't make a new skinframe as it
3167         // would cause all future lookups of this to be missing
3168         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3169         if (skinframe && skinframe->base)
3170                 return skinframe;
3171
3172         Image_StripImageExtension(name, basename, sizeof(basename));
3173
3174         // check for DDS texture file first
3175         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3176         {
3177                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3178                 if (basepixels == NULL)
3179                         return NULL;
3180         }
3181
3182         // FIXME handle miplevel
3183
3184         if (developer_loading.integer)
3185                 Con_Printf("loading skin \"%s\"\n", name);
3186
3187         // we've got some pixels to store, so really allocate this new texture now
3188         if (!skinframe)
3189                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3190         skinframe->stain = NULL;
3191         skinframe->merged = NULL;
3192         skinframe->base = NULL;
3193         skinframe->pants = NULL;
3194         skinframe->shirt = NULL;
3195         skinframe->nmap = NULL;
3196         skinframe->gloss = NULL;
3197         skinframe->glow = NULL;
3198         skinframe->fog = NULL;
3199         skinframe->reflect = NULL;
3200         skinframe->hasalpha = false;
3201
3202         if (ddsbase)
3203         {
3204                 skinframe->base = ddsbase;
3205                 skinframe->hasalpha = ddshasalpha;
3206                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3207                 if (r_loadfog && skinframe->hasalpha)
3208                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3209                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3210         }
3211         else
3212         {
3213                 basepixels_width = image_width;
3214                 basepixels_height = image_height;
3215                 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);
3216                 if (textureflags & TEXF_ALPHA)
3217                 {
3218                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3219                         {
3220                                 if (basepixels[j] < 255)
3221                                 {
3222                                         skinframe->hasalpha = true;
3223                                         break;
3224                                 }
3225                         }
3226                         if (r_loadfog && skinframe->hasalpha)
3227                         {
3228                                 // has transparent pixels
3229                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3230                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3231                                 {
3232                                         pixels[j+0] = 255;
3233                                         pixels[j+1] = 255;
3234                                         pixels[j+2] = 255;
3235                                         pixels[j+3] = basepixels[j+3];
3236                                 }
3237                                 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);
3238                                 Mem_Free(pixels);
3239                         }
3240                 }
3241                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3242                 //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]);
3243                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3244                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3245                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3246                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3247         }
3248
3249         if (r_loaddds)
3250         {
3251                 mymiplevel = savemiplevel;
3252                 if (r_loadnormalmap)
3253                         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);
3254                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3255                 if (r_loadgloss)
3256                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3257                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3258                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3259                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3260         }
3261
3262         // _norm is the name used by tenebrae and has been adopted as standard
3263         if (r_loadnormalmap && skinframe->nmap == NULL)
3264         {
3265                 mymiplevel = savemiplevel;
3266                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3267                 {
3268                         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);
3269                         Mem_Free(pixels);
3270                         pixels = NULL;
3271                 }
3272                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3273                 {
3274                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3275                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3276                         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);
3277                         Mem_Free(pixels);
3278                         Mem_Free(bumppixels);
3279                 }
3280                 else if (r_shadow_bumpscale_basetexture.value > 0)
3281                 {
3282                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3283                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3284                         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);
3285                         Mem_Free(pixels);
3286                 }
3287                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3288                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3289         }
3290
3291         // _luma is supported only for tenebrae compatibility
3292         // _glow is the preferred name
3293         mymiplevel = savemiplevel;
3294         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))))
3295         {
3296                 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);
3297                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3298                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3299                 Mem_Free(pixels);pixels = NULL;
3300         }
3301
3302         mymiplevel = savemiplevel;
3303         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3304         {
3305                 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);
3306                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3307                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3308                 Mem_Free(pixels);
3309                 pixels = NULL;
3310         }
3311
3312         mymiplevel = savemiplevel;
3313         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3314         {
3315                 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);
3316                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3317                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3318                 Mem_Free(pixels);
3319                 pixels = NULL;
3320         }
3321
3322         mymiplevel = savemiplevel;
3323         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3324         {
3325                 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);
3326                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3327                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3328                 Mem_Free(pixels);
3329                 pixels = NULL;
3330         }
3331
3332         mymiplevel = savemiplevel;
3333         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3334         {
3335                 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);
3336                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3337                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3338                 Mem_Free(pixels);
3339                 pixels = NULL;
3340         }
3341
3342         if (basepixels)
3343                 Mem_Free(basepixels);
3344
3345         return skinframe;
3346 }
3347
3348 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3349 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3350 {
3351         int i;
3352         unsigned char *temp1, *temp2;
3353         skinframe_t *skinframe;
3354
3355         if (cls.state == ca_dedicated)
3356                 return NULL;
3357
3358         // if already loaded just return it, otherwise make a new skinframe
3359         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3360         if (skinframe && skinframe->base)
3361                 return skinframe;
3362
3363         skinframe->stain = NULL;
3364         skinframe->merged = NULL;
3365         skinframe->base = NULL;
3366         skinframe->pants = NULL;
3367         skinframe->shirt = NULL;
3368         skinframe->nmap = NULL;
3369         skinframe->gloss = NULL;
3370         skinframe->glow = NULL;
3371         skinframe->fog = NULL;
3372         skinframe->reflect = NULL;
3373         skinframe->hasalpha = false;
3374
3375         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3376         if (!skindata)
3377                 return NULL;
3378
3379         if (developer_loading.integer)
3380                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3381
3382         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3383         {
3384                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3385                 temp2 = temp1 + width * height * 4;
3386                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3387                 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);
3388                 Mem_Free(temp1);
3389         }
3390         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3391         if (textureflags & TEXF_ALPHA)
3392         {
3393                 for (i = 3;i < width * height * 4;i += 4)
3394                 {
3395                         if (skindata[i] < 255)
3396                         {
3397                                 skinframe->hasalpha = true;
3398                                 break;
3399                         }
3400                 }
3401                 if (r_loadfog && skinframe->hasalpha)
3402                 {
3403                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3404                         memcpy(fogpixels, skindata, width * height * 4);
3405                         for (i = 0;i < width * height * 4;i += 4)
3406                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3407                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3408                         Mem_Free(fogpixels);
3409                 }
3410         }
3411
3412         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3413         //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]);
3414
3415         return skinframe;
3416 }
3417
3418 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3419 {
3420         int i;
3421         int featuresmask;
3422         skinframe_t *skinframe;
3423
3424         if (cls.state == ca_dedicated)
3425                 return NULL;
3426
3427         // if already loaded just return it, otherwise make a new skinframe
3428         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3429         if (skinframe && skinframe->base)
3430                 return skinframe;
3431
3432         skinframe->stain = NULL;
3433         skinframe->merged = NULL;
3434         skinframe->base = NULL;
3435         skinframe->pants = NULL;
3436         skinframe->shirt = NULL;
3437         skinframe->nmap = NULL;
3438         skinframe->gloss = NULL;
3439         skinframe->glow = NULL;
3440         skinframe->fog = NULL;
3441         skinframe->reflect = NULL;
3442         skinframe->hasalpha = false;
3443
3444         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3445         if (!skindata)
3446                 return NULL;
3447
3448         if (developer_loading.integer)
3449                 Con_Printf("loading quake skin \"%s\"\n", name);
3450
3451         // 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)
3452         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3453         memcpy(skinframe->qpixels, skindata, width*height);
3454         skinframe->qwidth = width;
3455         skinframe->qheight = height;
3456
3457         featuresmask = 0;
3458         for (i = 0;i < width * height;i++)
3459                 featuresmask |= palette_featureflags[skindata[i]];
3460
3461         skinframe->hasalpha = false;
3462         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3463         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3464         skinframe->qgeneratemerged = true;
3465         skinframe->qgeneratebase = skinframe->qhascolormapping;
3466         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3467
3468         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3469         //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]);
3470
3471         return skinframe;
3472 }
3473
3474 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3475 {
3476         int width;
3477         int height;
3478         unsigned char *skindata;
3479
3480         if (!skinframe->qpixels)
3481                 return;
3482
3483         if (!skinframe->qhascolormapping)
3484                 colormapped = false;
3485
3486         if (colormapped)
3487         {
3488                 if (!skinframe->qgeneratebase)
3489                         return;
3490         }
3491         else
3492         {
3493                 if (!skinframe->qgeneratemerged)
3494                         return;
3495         }
3496
3497         width = skinframe->qwidth;
3498         height = skinframe->qheight;
3499         skindata = skinframe->qpixels;
3500
3501         if (skinframe->qgeneratenmap)
3502         {
3503                 unsigned char *temp1, *temp2;
3504                 skinframe->qgeneratenmap = false;
3505                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3506                 temp2 = temp1 + width * height * 4;
3507                 // use either a custom palette or the quake palette
3508                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3509                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3510                 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);
3511                 Mem_Free(temp1);
3512         }
3513
3514         if (skinframe->qgenerateglow)
3515         {
3516                 skinframe->qgenerateglow = false;
3517                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3518         }
3519
3520         if (colormapped)
3521         {
3522                 skinframe->qgeneratebase = false;
3523                 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);
3524                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3525                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3526         }
3527         else
3528         {
3529                 skinframe->qgeneratemerged = false;
3530                 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);
3531         }
3532
3533         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3534         {
3535                 Mem_Free(skinframe->qpixels);
3536                 skinframe->qpixels = NULL;
3537         }
3538 }
3539
3540 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)
3541 {
3542         int i;
3543         skinframe_t *skinframe;
3544
3545         if (cls.state == ca_dedicated)
3546                 return NULL;
3547
3548         // if already loaded just return it, otherwise make a new skinframe
3549         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3550         if (skinframe && skinframe->base)
3551                 return skinframe;
3552
3553         skinframe->stain = NULL;
3554         skinframe->merged = NULL;
3555         skinframe->base = NULL;
3556         skinframe->pants = NULL;
3557         skinframe->shirt = NULL;
3558         skinframe->nmap = NULL;
3559         skinframe->gloss = NULL;
3560         skinframe->glow = NULL;
3561         skinframe->fog = NULL;
3562         skinframe->reflect = NULL;
3563         skinframe->hasalpha = false;
3564
3565         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3566         if (!skindata)
3567                 return NULL;
3568
3569         if (developer_loading.integer)
3570                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3571
3572         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3573         if (textureflags & TEXF_ALPHA)
3574         {
3575                 for (i = 0;i < width * height;i++)
3576                 {
3577                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3578                         {
3579                                 skinframe->hasalpha = true;
3580                                 break;
3581                         }
3582                 }
3583                 if (r_loadfog && skinframe->hasalpha)
3584                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3585         }
3586
3587         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3588         //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]);
3589
3590         return skinframe;
3591 }
3592
3593 skinframe_t *R_SkinFrame_LoadMissing(void)
3594 {
3595         skinframe_t *skinframe;
3596
3597         if (cls.state == ca_dedicated)
3598                 return NULL;
3599
3600         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3601         skinframe->stain = NULL;
3602         skinframe->merged = NULL;
3603         skinframe->base = NULL;
3604         skinframe->pants = NULL;
3605         skinframe->shirt = NULL;
3606         skinframe->nmap = NULL;
3607         skinframe->gloss = NULL;
3608         skinframe->glow = NULL;
3609         skinframe->fog = NULL;
3610         skinframe->reflect = NULL;
3611         skinframe->hasalpha = false;
3612
3613         skinframe->avgcolor[0] = rand() / RAND_MAX;
3614         skinframe->avgcolor[1] = rand() / RAND_MAX;
3615         skinframe->avgcolor[2] = rand() / RAND_MAX;
3616         skinframe->avgcolor[3] = 1;
3617
3618         return skinframe;
3619 }
3620
3621 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3622 typedef struct suffixinfo_s
3623 {
3624         const char *suffix;
3625         qboolean flipx, flipy, flipdiagonal;
3626 }
3627 suffixinfo_t;
3628 static suffixinfo_t suffix[3][6] =
3629 {
3630         {
3631                 {"px",   false, false, false},
3632                 {"nx",   false, false, false},
3633                 {"py",   false, false, false},
3634                 {"ny",   false, false, false},
3635                 {"pz",   false, false, false},
3636                 {"nz",   false, false, false}
3637         },
3638         {
3639                 {"posx", false, false, false},
3640                 {"negx", false, false, false},
3641                 {"posy", false, false, false},
3642                 {"negy", false, false, false},
3643                 {"posz", false, false, false},
3644                 {"negz", false, false, false}
3645         },
3646         {
3647                 {"rt",    true, false,  true},
3648                 {"lf",   false,  true,  true},
3649                 {"ft",    true,  true, false},
3650                 {"bk",   false, false, false},
3651                 {"up",    true, false,  true},
3652                 {"dn",    true, false,  true}
3653         }
3654 };
3655
3656 static int componentorder[4] = {0, 1, 2, 3};
3657
3658 rtexture_t *R_LoadCubemap(const char *basename)
3659 {
3660         int i, j, cubemapsize;
3661         unsigned char *cubemappixels, *image_buffer;
3662         rtexture_t *cubemaptexture;
3663         char name[256];
3664         // must start 0 so the first loadimagepixels has no requested width/height
3665         cubemapsize = 0;
3666         cubemappixels = NULL;
3667         cubemaptexture = NULL;
3668         // keep trying different suffix groups (posx, px, rt) until one loads
3669         for (j = 0;j < 3 && !cubemappixels;j++)
3670         {
3671                 // load the 6 images in the suffix group
3672                 for (i = 0;i < 6;i++)
3673                 {
3674                         // generate an image name based on the base and and suffix
3675                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3676                         // load it
3677                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3678                         {
3679                                 // an image loaded, make sure width and height are equal
3680                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3681                                 {
3682                                         // if this is the first image to load successfully, allocate the cubemap memory
3683                                         if (!cubemappixels && image_width >= 1)
3684                                         {
3685                                                 cubemapsize = image_width;
3686                                                 // note this clears to black, so unavailable sides are black
3687                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3688                                         }
3689                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3690                                         if (cubemappixels)
3691                                                 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);
3692                                 }
3693                                 else
3694                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3695                                 // free the image
3696                                 Mem_Free(image_buffer);
3697                         }
3698                 }
3699         }
3700         // if a cubemap loaded, upload it
3701         if (cubemappixels)
3702         {
3703                 if (developer_loading.integer)
3704                         Con_Printf("loading cubemap \"%s\"\n", basename);
3705
3706                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3707                 Mem_Free(cubemappixels);
3708         }
3709         else
3710         {
3711                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3712                 if (developer_loading.integer)
3713                 {
3714                         Con_Printf("(tried tried images ");
3715                         for (j = 0;j < 3;j++)
3716                                 for (i = 0;i < 6;i++)
3717                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3718                         Con_Print(" and was unable to find any of them).\n");
3719                 }
3720         }
3721         return cubemaptexture;
3722 }
3723
3724 rtexture_t *R_GetCubemap(const char *basename)
3725 {
3726         int i;
3727         for (i = 0;i < r_texture_numcubemaps;i++)
3728                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3729                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3730         if (i >= MAX_CUBEMAPS)
3731                 return r_texture_whitecube;
3732         r_texture_numcubemaps++;
3733         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3734         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3735         return r_texture_cubemaps[i].texture;
3736 }
3737
3738 void R_FreeCubemaps(void)
3739 {
3740         int i;
3741         for (i = 0;i < r_texture_numcubemaps;i++)
3742         {
3743                 if (developer_loading.integer)
3744                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3745                 if (r_texture_cubemaps[i].texture)
3746                         R_FreeTexture(r_texture_cubemaps[i].texture);
3747         }
3748         r_texture_numcubemaps = 0;
3749 }
3750
3751 void R_Main_FreeViewCache(void)
3752 {
3753         if (r_refdef.viewcache.entityvisible)
3754                 Mem_Free(r_refdef.viewcache.entityvisible);
3755         if (r_refdef.viewcache.world_pvsbits)
3756                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3757         if (r_refdef.viewcache.world_leafvisible)
3758                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3759         if (r_refdef.viewcache.world_surfacevisible)
3760                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3761         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3762 }
3763
3764 void R_Main_ResizeViewCache(void)
3765 {
3766         int numentities = r_refdef.scene.numentities;
3767         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3768         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3769         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3770         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3771         if (r_refdef.viewcache.maxentities < numentities)
3772         {
3773                 r_refdef.viewcache.maxentities = numentities;
3774                 if (r_refdef.viewcache.entityvisible)
3775                         Mem_Free(r_refdef.viewcache.entityvisible);
3776                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3777         }
3778         if (r_refdef.viewcache.world_numclusters != numclusters)
3779         {
3780                 r_refdef.viewcache.world_numclusters = numclusters;
3781                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3782                 if (r_refdef.viewcache.world_pvsbits)
3783                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3784                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3785         }
3786         if (r_refdef.viewcache.world_numleafs != numleafs)
3787         {
3788                 r_refdef.viewcache.world_numleafs = numleafs;
3789                 if (r_refdef.viewcache.world_leafvisible)
3790                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3791                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3792         }
3793         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3794         {
3795                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3796                 if (r_refdef.viewcache.world_surfacevisible)
3797                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3798                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3799         }
3800 }
3801
3802 extern rtexture_t *loadingscreentexture;
3803 void gl_main_start(void)
3804 {
3805         loadingscreentexture = NULL;
3806         r_texture_blanknormalmap = NULL;
3807         r_texture_white = NULL;
3808         r_texture_grey128 = NULL;
3809         r_texture_black = NULL;
3810         r_texture_whitecube = NULL;
3811         r_texture_normalizationcube = NULL;
3812         r_texture_fogattenuation = NULL;
3813         r_texture_fogheighttexture = NULL;
3814         r_texture_gammaramps = NULL;
3815         r_texture_numcubemaps = 0;
3816
3817         r_loaddds = r_texture_dds_load.integer != 0;
3818         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3819
3820         switch(vid.renderpath)
3821         {
3822         case RENDERPATH_GL20:
3823         case RENDERPATH_D3D9:
3824         case RENDERPATH_D3D10:
3825         case RENDERPATH_D3D11:
3826         case RENDERPATH_SOFT:
3827         case RENDERPATH_GLES2:
3828                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3829                 Cvar_SetValueQuick(&gl_combine, 1);
3830                 Cvar_SetValueQuick(&r_glsl, 1);
3831                 r_loadnormalmap = true;
3832                 r_loadgloss = true;
3833                 r_loadfog = false;
3834                 break;
3835         case RENDERPATH_GL13:
3836                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3837                 Cvar_SetValueQuick(&gl_combine, 1);
3838                 Cvar_SetValueQuick(&r_glsl, 0);
3839                 r_loadnormalmap = false;
3840                 r_loadgloss = false;
3841                 r_loadfog = true;
3842                 break;
3843         case RENDERPATH_GL11:
3844                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3845                 Cvar_SetValueQuick(&gl_combine, 0);
3846                 Cvar_SetValueQuick(&r_glsl, 0);
3847                 r_loadnormalmap = false;
3848                 r_loadgloss = false;
3849                 r_loadfog = true;
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_fog_clear);
4076         Cvar_RegisterVariable(&r_drawfog);
4077         Cvar_RegisterVariable(&r_transparentdepthmasking);
4078         Cvar_RegisterVariable(&r_texture_dds_load);
4079         Cvar_RegisterVariable(&r_texture_dds_save);
4080         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4081         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4082         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4083         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4084         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4085         Cvar_RegisterVariable(&r_textureunits);
4086         Cvar_RegisterVariable(&gl_combine);
4087         Cvar_RegisterVariable(&r_glsl);
4088         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4089         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4090         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4091         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4092         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4093         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4094         Cvar_RegisterVariable(&r_glsl_postprocess);
4095         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4096         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4097         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4098         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4099         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4100         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4101         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4102         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4103
4104         Cvar_RegisterVariable(&r_water);
4105         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4106         Cvar_RegisterVariable(&r_water_clippingplanebias);
4107         Cvar_RegisterVariable(&r_water_refractdistort);
4108         Cvar_RegisterVariable(&r_water_reflectdistort);
4109         Cvar_RegisterVariable(&r_water_scissormode);
4110         Cvar_RegisterVariable(&r_lerpsprites);
4111         Cvar_RegisterVariable(&r_lerpmodels);
4112         Cvar_RegisterVariable(&r_lerplightstyles);
4113         Cvar_RegisterVariable(&r_waterscroll);
4114         Cvar_RegisterVariable(&r_bloom);
4115         Cvar_RegisterVariable(&r_bloom_colorscale);
4116         Cvar_RegisterVariable(&r_bloom_brighten);
4117         Cvar_RegisterVariable(&r_bloom_blur);
4118         Cvar_RegisterVariable(&r_bloom_resolution);
4119         Cvar_RegisterVariable(&r_bloom_colorexponent);
4120         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4121         Cvar_RegisterVariable(&r_hdr);
4122         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4123         Cvar_RegisterVariable(&r_hdr_glowintensity);
4124         Cvar_RegisterVariable(&r_hdr_range);
4125         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4126         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4127         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4128         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4129         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4130         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4131         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4132         Cvar_RegisterVariable(&developer_texturelogging);
4133         Cvar_RegisterVariable(&gl_lightmaps);
4134         Cvar_RegisterVariable(&r_test);
4135         Cvar_RegisterVariable(&r_glsl_saturation);
4136         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4137         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4138         Cvar_RegisterVariable(&r_framedatasize);
4139         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4140                 Cvar_SetValue("r_fullbrights", 0);
4141         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4142
4143         Cvar_RegisterVariable(&r_track_sprites);
4144         Cvar_RegisterVariable(&r_track_sprites_flags);
4145         Cvar_RegisterVariable(&r_track_sprites_scalew);
4146         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4147         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4148         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4149         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4150         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4151 }
4152
4153 extern void R_Textures_Init(void);
4154 extern void GL_Draw_Init(void);
4155 extern void GL_Main_Init(void);
4156 extern void R_Shadow_Init(void);
4157 extern void R_Sky_Init(void);
4158 extern void GL_Surf_Init(void);
4159 extern void R_Particles_Init(void);
4160 extern void R_Explosion_Init(void);
4161 extern void gl_backend_init(void);
4162 extern void Sbar_Init(void);
4163 extern void R_LightningBeams_Init(void);
4164 extern void Mod_RenderInit(void);
4165 extern void Font_Init(void);
4166
4167 void Render_Init(void)
4168 {
4169         gl_backend_init();
4170         R_Textures_Init();
4171         GL_Main_Init();
4172         Font_Init();
4173         GL_Draw_Init();
4174         R_Shadow_Init();
4175         R_Sky_Init();
4176         GL_Surf_Init();
4177         Sbar_Init();
4178         R_Particles_Init();
4179         R_Explosion_Init();
4180         R_LightningBeams_Init();
4181         Mod_RenderInit();
4182 }
4183
4184 /*
4185 ===============
4186 GL_Init
4187 ===============
4188 */
4189 extern char *ENGINE_EXTENSIONS;
4190 void GL_Init (void)
4191 {
4192         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4193         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4194         gl_version = (const char *)qglGetString(GL_VERSION);
4195         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4196
4197         if (!gl_extensions)
4198                 gl_extensions = "";
4199         if (!gl_platformextensions)
4200                 gl_platformextensions = "";
4201
4202         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4203         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4204         Con_Printf("GL_VERSION: %s\n", gl_version);
4205         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4206         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4207
4208         VID_CheckExtensions();
4209
4210         // LordHavoc: report supported extensions
4211         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4212
4213         // clear to black (loading plaque will be seen over this)
4214         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4215 }
4216
4217 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4218 {
4219         int i;
4220         mplane_t *p;
4221         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4222         {
4223                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4224                 if (i == 4)
4225                         continue;
4226                 p = r_refdef.view.frustum + i;
4227                 switch(p->signbits)
4228                 {
4229                 default:
4230                 case 0:
4231                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4232                                 return true;
4233                         break;
4234                 case 1:
4235                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4236                                 return true;
4237                         break;
4238                 case 2:
4239                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4240                                 return true;
4241                         break;
4242                 case 3:
4243                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4244                                 return true;
4245                         break;
4246                 case 4:
4247                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4248                                 return true;
4249                         break;
4250                 case 5:
4251                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4252                                 return true;
4253                         break;
4254                 case 6:
4255                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4256                                 return true;
4257                         break;
4258                 case 7:
4259                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4260                                 return true;
4261                         break;
4262                 }
4263         }
4264         return false;
4265 }
4266
4267 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4268 {
4269         int i;
4270         const mplane_t *p;
4271         for (i = 0;i < numplanes;i++)
4272         {
4273                 p = planes + i;
4274                 switch(p->signbits)
4275                 {
4276                 default:
4277                 case 0:
4278                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4279                                 return true;
4280                         break;
4281                 case 1:
4282                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4283                                 return true;
4284                         break;
4285                 case 2:
4286                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4287                                 return true;
4288                         break;
4289                 case 3:
4290                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4291                                 return true;
4292                         break;
4293                 case 4:
4294                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4295                                 return true;
4296                         break;
4297                 case 5:
4298                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4299                                 return true;
4300                         break;
4301                 case 6:
4302                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4303                                 return true;
4304                         break;
4305                 case 7:
4306                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4307                                 return true;
4308                         break;
4309                 }
4310         }
4311         return false;
4312 }
4313
4314 //==================================================================================
4315
4316 // LordHavoc: this stores temporary data used within the same frame
4317
4318 typedef struct r_framedata_mem_s
4319 {
4320         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4321         size_t size; // how much usable space
4322         size_t current; // how much space in use
4323         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4324         size_t wantedsize; // how much space was allocated
4325         unsigned char *data; // start of real data (16byte aligned)
4326 }
4327 r_framedata_mem_t;
4328
4329 static r_framedata_mem_t *r_framedata_mem;
4330
4331 void R_FrameData_Reset(void)
4332 {
4333         while (r_framedata_mem)
4334         {
4335                 r_framedata_mem_t *next = r_framedata_mem->purge;
4336                 Mem_Free(r_framedata_mem);
4337                 r_framedata_mem = next;
4338         }
4339 }
4340
4341 void R_FrameData_Resize(void)
4342 {
4343         size_t wantedsize;
4344         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4345         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4346         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4347         {
4348                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4349                 newmem->wantedsize = wantedsize;
4350                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4351                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4352                 newmem->current = 0;
4353                 newmem->mark = 0;
4354                 newmem->purge = r_framedata_mem;
4355                 r_framedata_mem = newmem;
4356         }
4357 }
4358
4359 void R_FrameData_NewFrame(void)
4360 {
4361         R_FrameData_Resize();
4362         if (!r_framedata_mem)
4363                 return;
4364         // if we ran out of space on the last frame, free the old memory now
4365         while (r_framedata_mem->purge)
4366         {
4367                 // repeatedly remove the second item in the list, leaving only head
4368                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4369                 Mem_Free(r_framedata_mem->purge);
4370                 r_framedata_mem->purge = next;
4371         }
4372         // reset the current mem pointer
4373         r_framedata_mem->current = 0;
4374         r_framedata_mem->mark = 0;
4375 }
4376
4377 void *R_FrameData_Alloc(size_t size)
4378 {
4379         void *data;
4380
4381         // align to 16 byte boundary - the data pointer is already aligned, so we
4382         // only need to ensure the size of every allocation is also aligned
4383         size = (size + 15) & ~15;
4384
4385         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4386         {
4387                 // emergency - we ran out of space, allocate more memory
4388                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4389                 R_FrameData_Resize();
4390         }
4391
4392         data = r_framedata_mem->data + r_framedata_mem->current;
4393         r_framedata_mem->current += size;
4394
4395         // count the usage for stats
4396         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4397         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4398
4399         return (void *)data;
4400 }
4401
4402 void *R_FrameData_Store(size_t size, void *data)
4403 {
4404         void *d = R_FrameData_Alloc(size);
4405         if (d && data)
4406                 memcpy(d, data, size);
4407         return d;
4408 }
4409
4410 void R_FrameData_SetMark(void)
4411 {
4412         if (!r_framedata_mem)
4413                 return;
4414         r_framedata_mem->mark = r_framedata_mem->current;
4415 }
4416
4417 void R_FrameData_ReturnToMark(void)
4418 {
4419         if (!r_framedata_mem)
4420                 return;
4421         r_framedata_mem->current = r_framedata_mem->mark;
4422 }
4423
4424 //==================================================================================
4425
4426 // LordHavoc: animcache originally written by Echon, rewritten since then
4427
4428 /**
4429  * Animation cache prevents re-generating mesh data for an animated model
4430  * multiple times in one frame for lighting, shadowing, reflections, etc.
4431  */
4432
4433 void R_AnimCache_Free(void)
4434 {
4435 }
4436
4437 void R_AnimCache_ClearCache(void)
4438 {
4439         int i;
4440         entity_render_t *ent;
4441
4442         for (i = 0;i < r_refdef.scene.numentities;i++)
4443         {
4444                 ent = r_refdef.scene.entities[i];
4445                 ent->animcache_vertex3f = NULL;
4446                 ent->animcache_normal3f = NULL;
4447                 ent->animcache_svector3f = NULL;
4448                 ent->animcache_tvector3f = NULL;
4449                 ent->animcache_vertexmesh = NULL;
4450                 ent->animcache_vertex3fbuffer = NULL;
4451                 ent->animcache_vertexmeshbuffer = NULL;
4452         }
4453 }
4454
4455 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4456 {
4457         int i;
4458
4459         // check if we need the meshbuffers
4460         if (!vid.useinterleavedarrays)
4461                 return;
4462
4463         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4464                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4465         // TODO: upload vertex3f buffer?
4466         if (ent->animcache_vertexmesh)
4467         {
4468                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4469                 for (i = 0;i < numvertices;i++)
4470                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4471                 if (ent->animcache_svector3f)
4472                         for (i = 0;i < numvertices;i++)
4473                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4474                 if (ent->animcache_tvector3f)
4475                         for (i = 0;i < numvertices;i++)
4476                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4477                 if (ent->animcache_normal3f)
4478                         for (i = 0;i < numvertices;i++)
4479                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4480                 // TODO: upload vertexmeshbuffer?
4481         }
4482 }
4483
4484 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4485 {
4486         dp_model_t *model = ent->model;
4487         int numvertices;
4488         // see if it's already cached this frame
4489         if (ent->animcache_vertex3f)
4490         {
4491                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4492                 if (wantnormals || wanttangents)
4493                 {
4494                         if (ent->animcache_normal3f)
4495                                 wantnormals = false;
4496                         if (ent->animcache_svector3f)
4497                                 wanttangents = false;
4498                         if (wantnormals || wanttangents)
4499                         {
4500                                 numvertices = model->surfmesh.num_vertices;
4501                                 if (wantnormals)
4502                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4503                                 if (wanttangents)
4504                                 {
4505                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4506                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4507                                 }
4508                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4509                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4510                         }
4511                 }
4512         }
4513         else
4514         {
4515                 // see if this ent is worth caching
4516                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4517                         return false;
4518                 // get some memory for this entity and generate mesh data
4519                 numvertices = model->surfmesh.num_vertices;
4520                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4521                 if (wantnormals)
4522                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4523                 if (wanttangents)
4524                 {
4525                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4526                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4527                 }
4528                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4529                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4530         }
4531         return true;
4532 }
4533
4534 void R_AnimCache_CacheVisibleEntities(void)
4535 {
4536         int i;
4537         qboolean wantnormals = true;
4538         qboolean wanttangents = !r_showsurfaces.integer;
4539
4540         switch(vid.renderpath)
4541         {
4542         case RENDERPATH_GL20:
4543         case RENDERPATH_D3D9:
4544         case RENDERPATH_D3D10:
4545         case RENDERPATH_D3D11:
4546         case RENDERPATH_GLES2:
4547                 break;
4548         case RENDERPATH_GL13:
4549         case RENDERPATH_GL11:
4550                 wanttangents = false;
4551                 break;
4552         case RENDERPATH_SOFT:
4553                 break;
4554         }
4555
4556         if (r_shownormals.integer)
4557                 wanttangents = wantnormals = true;
4558
4559         // TODO: thread this
4560         // NOTE: R_PrepareRTLights() also caches entities
4561
4562         for (i = 0;i < r_refdef.scene.numentities;i++)
4563                 if (r_refdef.viewcache.entityvisible[i])
4564                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4565 }
4566
4567 //==================================================================================
4568
4569 static void R_View_UpdateEntityLighting (void)
4570 {
4571         int i;
4572         entity_render_t *ent;
4573         vec3_t tempdiffusenormal, avg;
4574         vec_t f, fa, fd, fdd;
4575         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4576
4577         for (i = 0;i < r_refdef.scene.numentities;i++)
4578         {
4579                 ent = r_refdef.scene.entities[i];
4580
4581                 // skip unseen models
4582                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4583                         continue;
4584
4585                 // skip bsp models
4586                 if (ent->model && ent->model->brush.num_leafs)
4587                 {
4588                         // TODO: use modellight for r_ambient settings on world?
4589                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4590                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4591                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4592                         continue;
4593                 }
4594
4595                 // fetch the lighting from the worldmodel data
4596                 VectorClear(ent->modellight_ambient);
4597                 VectorClear(ent->modellight_diffuse);
4598                 VectorClear(tempdiffusenormal);
4599                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4600                 {
4601                         vec3_t org;
4602                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4603
4604                         // complete lightning for lit sprites
4605                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4606                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4607                         {
4608                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4609                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4610                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4611                         }
4612                         else
4613                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4614
4615                         if(ent->flags & RENDER_EQUALIZE)
4616                         {
4617                                 // first fix up ambient lighting...
4618                                 if(r_equalize_entities_minambient.value > 0)
4619                                 {
4620                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4621                                         if(fd > 0)
4622                                         {
4623                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4624                                                 if(fa < r_equalize_entities_minambient.value * fd)
4625                                                 {
4626                                                         // solve:
4627                                                         //   fa'/fd' = minambient
4628                                                         //   fa'+0.25*fd' = fa+0.25*fd
4629                                                         //   ...
4630                                                         //   fa' = fd' * minambient
4631                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4632                                                         //   ...
4633                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4634                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4635                                                         //   ...
4636                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4637                                                         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
4638                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4639                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4640                                                 }
4641                                         }
4642                                 }
4643
4644                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4645                                 {
4646                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4647                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4648                                         f = fa + 0.25 * fd;
4649                                         if(f > 0)
4650                                         {
4651                                                 // adjust brightness and saturation to target
4652                                                 avg[0] = avg[1] = avg[2] = fa / f;
4653                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4654                                                 avg[0] = avg[1] = avg[2] = fd / f;
4655                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4656                                         }
4657                                 }
4658                         }
4659                 }
4660                 else // highly rare
4661                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4662
4663                 // move the light direction into modelspace coordinates for lighting code
4664                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4665                 if(VectorLength2(ent->modellight_lightdir) == 0)
4666                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4667                 VectorNormalize(ent->modellight_lightdir);
4668         }
4669 }
4670
4671 #define MAX_LINEOFSIGHTTRACES 64
4672
4673 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4674 {
4675         int i;
4676         vec3_t boxmins, boxmaxs;
4677         vec3_t start;
4678         vec3_t end;
4679         dp_model_t *model = r_refdef.scene.worldmodel;
4680
4681         if (!model || !model->brush.TraceLineOfSight)
4682                 return true;
4683
4684         // expand the box a little
4685         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4686         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4687         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4688         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4689         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4690         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4691
4692         // return true if eye is inside enlarged box
4693         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4694                 return true;
4695
4696         // try center
4697         VectorCopy(eye, start);
4698         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4699         if (model->brush.TraceLineOfSight(model, start, end))
4700                 return true;
4701
4702         // try various random positions
4703         for (i = 0;i < numsamples;i++)
4704         {
4705                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4706                 if (model->brush.TraceLineOfSight(model, start, end))
4707                         return true;
4708         }
4709
4710         return false;
4711 }
4712
4713
4714 static void R_View_UpdateEntityVisible (void)
4715 {
4716         int i;
4717         int renderimask;
4718         int samples;
4719         entity_render_t *ent;
4720
4721         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4722                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4723                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4724                 :                                                          RENDER_EXTERIORMODEL;
4725         if (!r_drawviewmodel.integer)
4726                 renderimask |= RENDER_VIEWMODEL;
4727         if (!r_drawexteriormodel.integer)
4728                 renderimask |= RENDER_EXTERIORMODEL;
4729         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4730         {
4731                 // worldmodel can check visibility
4732                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4733                 for (i = 0;i < r_refdef.scene.numentities;i++)
4734                 {
4735                         ent = r_refdef.scene.entities[i];
4736                         if (!(ent->flags & renderimask))
4737                         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)))
4738                         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))
4739                                 r_refdef.viewcache.entityvisible[i] = true;
4740                 }
4741                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4742                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4743                 {
4744                         for (i = 0;i < r_refdef.scene.numentities;i++)
4745                         {
4746                                 ent = r_refdef.scene.entities[i];
4747                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4748                                 {
4749                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4750                                         if (samples < 0)
4751                                                 continue; // temp entities do pvs only
4752                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4753                                                 ent->last_trace_visibility = realtime;
4754                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4755                                                 r_refdef.viewcache.entityvisible[i] = 0;
4756                                 }
4757                         }
4758                 }
4759         }
4760         else
4761         {
4762                 // no worldmodel or it can't check visibility
4763                 for (i = 0;i < r_refdef.scene.numentities;i++)
4764                 {
4765                         ent = r_refdef.scene.entities[i];
4766                         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));
4767                 }
4768         }
4769 }
4770
4771 /// only used if skyrendermasked, and normally returns false
4772 int R_DrawBrushModelsSky (void)
4773 {
4774         int i, sky;
4775         entity_render_t *ent;
4776
4777         sky = false;
4778         for (i = 0;i < r_refdef.scene.numentities;i++)
4779         {
4780                 if (!r_refdef.viewcache.entityvisible[i])
4781                         continue;
4782                 ent = r_refdef.scene.entities[i];
4783                 if (!ent->model || !ent->model->DrawSky)
4784                         continue;
4785                 ent->model->DrawSky(ent);
4786                 sky = true;
4787         }
4788         return sky;
4789 }
4790
4791 static void R_DrawNoModel(entity_render_t *ent);
4792 static void R_DrawModels(void)
4793 {
4794         int i;
4795         entity_render_t *ent;
4796
4797         for (i = 0;i < r_refdef.scene.numentities;i++)
4798         {
4799                 if (!r_refdef.viewcache.entityvisible[i])
4800                         continue;
4801                 ent = r_refdef.scene.entities[i];
4802                 r_refdef.stats.entities++;
4803                 if (ent->model && ent->model->Draw != NULL)
4804                         ent->model->Draw(ent);
4805                 else
4806                         R_DrawNoModel(ent);
4807         }
4808 }
4809
4810 static void R_DrawModelsDepth(void)
4811 {
4812         int i;
4813         entity_render_t *ent;
4814
4815         for (i = 0;i < r_refdef.scene.numentities;i++)
4816         {
4817                 if (!r_refdef.viewcache.entityvisible[i])
4818                         continue;
4819                 ent = r_refdef.scene.entities[i];
4820                 if (ent->model && ent->model->DrawDepth != NULL)
4821                         ent->model->DrawDepth(ent);
4822         }
4823 }
4824
4825 static void R_DrawModelsDebug(void)
4826 {
4827         int i;
4828         entity_render_t *ent;
4829
4830         for (i = 0;i < r_refdef.scene.numentities;i++)
4831         {
4832                 if (!r_refdef.viewcache.entityvisible[i])
4833                         continue;
4834                 ent = r_refdef.scene.entities[i];
4835                 if (ent->model && ent->model->DrawDebug != NULL)
4836                         ent->model->DrawDebug(ent);
4837         }
4838 }
4839
4840 static void R_DrawModelsAddWaterPlanes(void)
4841 {
4842         int i;
4843         entity_render_t *ent;
4844
4845         for (i = 0;i < r_refdef.scene.numentities;i++)
4846         {
4847                 if (!r_refdef.viewcache.entityvisible[i])
4848                         continue;
4849                 ent = r_refdef.scene.entities[i];
4850                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4851                         ent->model->DrawAddWaterPlanes(ent);
4852         }
4853 }
4854
4855 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4856 {
4857         if (r_hdr_irisadaptation.integer)
4858         {
4859                 vec3_t ambient;
4860                 vec3_t diffuse;
4861                 vec3_t diffusenormal;
4862                 vec_t brightness;
4863                 vec_t goal;
4864                 vec_t adjust;
4865                 vec_t current;
4866                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4867                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4868                 brightness = max(0.0000001f, brightness);
4869                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4870                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4871                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4872                 current = r_hdr_irisadaptation_value.value;
4873                 if (current < goal)
4874                         current = min(current + adjust, goal);
4875                 else if (current > goal)
4876                         current = max(current - adjust, goal);
4877                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4878                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4879         }
4880         else if (r_hdr_irisadaptation_value.value != 1.0f)
4881                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4882 }
4883
4884 static void R_View_SetFrustum(const int *scissor)
4885 {
4886         int i;
4887         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4888         vec3_t forward, left, up, origin, v;
4889
4890         if(scissor)
4891         {
4892                 // flipped x coordinates (because x points left here)
4893                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4894                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4895
4896                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4897                 switch(vid.renderpath)
4898                 {
4899                         case RENDERPATH_D3D9:
4900                         case RENDERPATH_D3D10:
4901                         case RENDERPATH_D3D11:
4902                                 // non-flipped y coordinates
4903                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4904                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4905                                 break;
4906                         case RENDERPATH_SOFT:
4907                         case RENDERPATH_GL11:
4908                         case RENDERPATH_GL13:
4909                         case RENDERPATH_GL20:
4910                         case RENDERPATH_GLES2:
4911                                 // non-flipped y coordinates
4912                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4913                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4914                                 break;
4915                 }
4916         }
4917
4918         // we can't trust r_refdef.view.forward and friends in reflected scenes
4919         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4920
4921 #if 0
4922         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4923         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4924         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4925         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4926         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4927         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4928         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4929         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4930         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4931         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4932         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4933         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4934 #endif
4935
4936 #if 0
4937         zNear = r_refdef.nearclip;
4938         nudge = 1.0 - 1.0 / (1<<23);
4939         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4940         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4941         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4942         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4943         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4944         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4945         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4946         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4947 #endif
4948
4949
4950
4951 #if 0
4952         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4953         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4954         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4955         r_refdef.view.frustum[0].dist = m[15] - m[12];
4956
4957         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4958         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4959         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4960         r_refdef.view.frustum[1].dist = m[15] + m[12];
4961
4962         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4963         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4964         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4965         r_refdef.view.frustum[2].dist = m[15] - m[13];
4966
4967         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4968         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4969         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4970         r_refdef.view.frustum[3].dist = m[15] + m[13];
4971
4972         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4973         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4974         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4975         r_refdef.view.frustum[4].dist = m[15] - m[14];
4976
4977         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4978         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4979         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4980         r_refdef.view.frustum[5].dist = m[15] + m[14];
4981 #endif
4982
4983         if (r_refdef.view.useperspective)
4984         {
4985                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4986                 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]);
4987                 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]);
4988                 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]);
4989                 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]);
4990
4991                 // then the normals from the corners relative to origin
4992                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4993                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4994                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4995                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4996
4997                 // in a NORMAL view, forward cross left == up
4998                 // in a REFLECTED view, forward cross left == down
4999                 // so our cross products above need to be adjusted for a left handed coordinate system
5000                 CrossProduct(forward, left, v);
5001                 if(DotProduct(v, up) < 0)
5002                 {
5003                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5004                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5005                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5006                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5007                 }
5008
5009                 // Leaving those out was a mistake, those were in the old code, and they
5010                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5011                 // I couldn't reproduce it after adding those normalizations. --blub
5012                 VectorNormalize(r_refdef.view.frustum[0].normal);
5013                 VectorNormalize(r_refdef.view.frustum[1].normal);
5014                 VectorNormalize(r_refdef.view.frustum[2].normal);
5015                 VectorNormalize(r_refdef.view.frustum[3].normal);
5016
5017                 // make the corners absolute
5018                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5019                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5020                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5021                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5022
5023                 // one more normal
5024                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5025
5026                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5027                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5028                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5029                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5030                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5031         }
5032         else
5033         {
5034                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5035                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5036                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5037                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5038                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5039                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5040                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5041                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5042                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5043                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5044         }
5045         r_refdef.view.numfrustumplanes = 5;
5046
5047         if (r_refdef.view.useclipplane)
5048         {
5049                 r_refdef.view.numfrustumplanes = 6;
5050                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5051         }
5052
5053         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5054                 PlaneClassify(r_refdef.view.frustum + i);
5055
5056         // LordHavoc: note to all quake engine coders, Quake had a special case
5057         // for 90 degrees which assumed a square view (wrong), so I removed it,
5058         // Quake2 has it disabled as well.
5059
5060         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5061         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5062         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5063         //PlaneClassify(&frustum[0]);
5064
5065         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5066         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5067         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5068         //PlaneClassify(&frustum[1]);
5069
5070         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5071         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5072         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5073         //PlaneClassify(&frustum[2]);
5074
5075         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5076         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5077         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5078         //PlaneClassify(&frustum[3]);
5079
5080         // nearclip plane
5081         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5082         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5083         //PlaneClassify(&frustum[4]);
5084 }
5085
5086 void R_View_UpdateWithScissor(const int *myscissor)
5087 {
5088         R_Main_ResizeViewCache();
5089         R_View_SetFrustum(myscissor);
5090         R_View_WorldVisibility(r_refdef.view.useclipplane);
5091         R_View_UpdateEntityVisible();
5092         R_View_UpdateEntityLighting();
5093 }
5094
5095 void R_View_Update(void)
5096 {
5097         R_Main_ResizeViewCache();
5098         R_View_SetFrustum(NULL);
5099         R_View_WorldVisibility(r_refdef.view.useclipplane);
5100         R_View_UpdateEntityVisible();
5101         R_View_UpdateEntityLighting();
5102 }
5103
5104 void R_SetupView(qboolean allowwaterclippingplane)
5105 {
5106         const float *customclipplane = NULL;
5107         float plane[4];
5108         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5109         {
5110                 // LordHavoc: couldn't figure out how to make this approach the
5111                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5112                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5113                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5114                         dist = r_refdef.view.clipplane.dist;
5115                 plane[0] = r_refdef.view.clipplane.normal[0];
5116                 plane[1] = r_refdef.view.clipplane.normal[1];
5117                 plane[2] = r_refdef.view.clipplane.normal[2];
5118                 plane[3] = dist;
5119                 customclipplane = plane;
5120         }
5121
5122         if (!r_refdef.view.useperspective)
5123                 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);
5124         else if (vid.stencil && r_useinfinitefarclip.integer)
5125                 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);
5126         else
5127                 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);
5128         R_SetViewport(&r_refdef.view.viewport);
5129 }
5130
5131 void R_EntityMatrix(const matrix4x4_t *matrix)
5132 {
5133         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5134         {
5135                 gl_modelmatrixchanged = false;
5136                 gl_modelmatrix = *matrix;
5137                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5138                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5139                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5140                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5141                 CHECKGLERROR
5142                 switch(vid.renderpath)
5143                 {
5144                 case RENDERPATH_D3D9:
5145 #ifdef SUPPORTD3D
5146                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5147                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5148 #endif
5149                         break;
5150                 case RENDERPATH_D3D10:
5151                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5152                         break;
5153                 case RENDERPATH_D3D11:
5154                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5155                         break;
5156                 case RENDERPATH_GL13:
5157                 case RENDERPATH_GL11:
5158                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5159                         break;
5160                 case RENDERPATH_SOFT:
5161                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5162                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5163                         break;
5164                 case RENDERPATH_GL20:
5165                 case RENDERPATH_GLES2:
5166                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5167                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5168                         break;
5169                 }
5170         }
5171 }
5172
5173 void R_ResetViewRendering2D(void)
5174 {
5175         r_viewport_t viewport;
5176         DrawQ_Finish();
5177
5178         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5179         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);
5180         R_SetViewport(&viewport);
5181         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5182         GL_Color(1, 1, 1, 1);
5183         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5184         GL_BlendFunc(GL_ONE, GL_ZERO);
5185         GL_ScissorTest(false);
5186         GL_DepthMask(false);
5187         GL_DepthRange(0, 1);
5188         GL_DepthTest(false);
5189         GL_DepthFunc(GL_LEQUAL);
5190         R_EntityMatrix(&identitymatrix);
5191         R_Mesh_ResetTextureState();
5192         GL_PolygonOffset(0, 0);
5193         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5194         switch(vid.renderpath)
5195         {
5196         case RENDERPATH_GL11:
5197         case RENDERPATH_GL13:
5198         case RENDERPATH_GL20:
5199         case RENDERPATH_GLES2:
5200                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5201                 break;
5202         case RENDERPATH_D3D9:
5203         case RENDERPATH_D3D10:
5204         case RENDERPATH_D3D11:
5205         case RENDERPATH_SOFT:
5206                 break;
5207         }
5208         GL_CullFace(GL_NONE);
5209 }
5210
5211 void R_ResetViewRendering3D(void)
5212 {
5213         DrawQ_Finish();
5214
5215         R_SetupView(true);
5216         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5217         GL_Color(1, 1, 1, 1);
5218         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5219         GL_BlendFunc(GL_ONE, GL_ZERO);
5220         GL_ScissorTest(true);
5221         GL_DepthMask(true);
5222         GL_DepthRange(0, 1);
5223         GL_DepthTest(true);
5224         GL_DepthFunc(GL_LEQUAL);
5225         R_EntityMatrix(&identitymatrix);
5226         R_Mesh_ResetTextureState();
5227         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5228         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5229         switch(vid.renderpath)
5230         {
5231         case RENDERPATH_GL11:
5232         case RENDERPATH_GL13:
5233         case RENDERPATH_GL20:
5234         case RENDERPATH_GLES2:
5235                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5236                 break;
5237         case RENDERPATH_D3D9:
5238         case RENDERPATH_D3D10:
5239         case RENDERPATH_D3D11:
5240         case RENDERPATH_SOFT:
5241                 break;
5242         }
5243         GL_CullFace(r_refdef.view.cullface_back);
5244 }
5245
5246 /*
5247 ================
5248 R_RenderView_UpdateViewVectors
5249 ================
5250 */
5251 static void R_RenderView_UpdateViewVectors(void)
5252 {
5253         // break apart the view matrix into vectors for various purposes
5254         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5255         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5256         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5257         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5258         // make an inverted copy of the view matrix for tracking sprites
5259         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5260 }
5261
5262 void R_RenderScene(void);
5263 void R_RenderWaterPlanes(void);
5264
5265 static void R_Water_StartFrame(void)
5266 {
5267         int i;
5268         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5269         r_waterstate_waterplane_t *p;
5270
5271         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5272                 return;
5273
5274         switch(vid.renderpath)
5275         {
5276         case RENDERPATH_GL20:
5277         case RENDERPATH_D3D9:
5278         case RENDERPATH_D3D10:
5279         case RENDERPATH_D3D11:
5280         case RENDERPATH_SOFT:
5281         case RENDERPATH_GLES2:
5282                 break;
5283         case RENDERPATH_GL13:
5284         case RENDERPATH_GL11:
5285                 return;
5286         }
5287
5288         // set waterwidth and waterheight to the water resolution that will be
5289         // used (often less than the screen resolution for faster rendering)
5290         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5291         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5292
5293         // calculate desired texture sizes
5294         // can't use water if the card does not support the texture size
5295         if (!r_water.integer || r_showsurfaces.integer)
5296                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5297         else if (vid.support.arb_texture_non_power_of_two)
5298         {
5299                 texturewidth = waterwidth;
5300                 textureheight = waterheight;
5301                 camerawidth = waterwidth;
5302                 cameraheight = waterheight;
5303         }
5304         else
5305         {
5306                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5307                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5308                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5309                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5310         }
5311
5312         // allocate textures as needed
5313         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5314         {
5315                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5316                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5317                 {
5318                         if (p->texture_refraction)
5319                                 R_FreeTexture(p->texture_refraction);
5320                         p->texture_refraction = NULL;
5321                         if (p->texture_reflection)
5322                                 R_FreeTexture(p->texture_reflection);
5323                         p->texture_reflection = NULL;
5324                         if (p->texture_camera)
5325                                 R_FreeTexture(p->texture_camera);
5326                         p->texture_camera = NULL;
5327                 }
5328                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5329                 r_waterstate.texturewidth = texturewidth;
5330                 r_waterstate.textureheight = textureheight;
5331                 r_waterstate.camerawidth = camerawidth;
5332                 r_waterstate.cameraheight = cameraheight;
5333         }
5334
5335         if (r_waterstate.texturewidth)
5336         {
5337                 r_waterstate.enabled = true;
5338
5339                 // when doing a reduced render (HDR) we want to use a smaller area
5340                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5341                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5342
5343                 // set up variables that will be used in shader setup
5344                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5345                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5346                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5347                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5348         }
5349
5350         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5351         r_waterstate.numwaterplanes = 0;
5352 }
5353
5354 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5355 {
5356         int triangleindex, planeindex;
5357         const int *e;
5358         vec3_t vert[3];
5359         vec3_t normal;
5360         vec3_t center;
5361         mplane_t plane;
5362         r_waterstate_waterplane_t *p;
5363         texture_t *t = R_GetCurrentTexture(surface->texture);
5364
5365         // just use the first triangle with a valid normal for any decisions
5366         VectorClear(normal);
5367         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5368         {
5369                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5370                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5371                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5372                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5373                 if (VectorLength2(normal) >= 0.001)
5374                         break;
5375         }
5376
5377         VectorCopy(normal, plane.normal);
5378         VectorNormalize(plane.normal);
5379         plane.dist = DotProduct(vert[0], plane.normal);
5380         PlaneClassify(&plane);
5381         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5382         {
5383                 // skip backfaces (except if nocullface is set)
5384                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5385                         return;
5386                 VectorNegate(plane.normal, plane.normal);
5387                 plane.dist *= -1;
5388                 PlaneClassify(&plane);
5389         }
5390
5391
5392         // find a matching plane if there is one
5393         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5394                 if(p->camera_entity == t->camera_entity)
5395                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5396                                 break;
5397         if (planeindex >= r_waterstate.maxwaterplanes)
5398                 return; // nothing we can do, out of planes
5399
5400         // if this triangle does not fit any known plane rendered this frame, add one
5401         if (planeindex >= r_waterstate.numwaterplanes)
5402         {
5403                 // store the new plane
5404                 r_waterstate.numwaterplanes++;
5405                 p->plane = plane;
5406                 // clear materialflags and pvs
5407                 p->materialflags = 0;
5408                 p->pvsvalid = false;
5409                 p->camera_entity = t->camera_entity;
5410                 VectorCopy(surface->mins, p->mins);
5411                 VectorCopy(surface->maxs, p->maxs);
5412         }
5413         else
5414         {
5415                 // merge mins/maxs
5416                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5417                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5418                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5419                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5420                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5421                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5422         }
5423         // merge this surface's materialflags into the waterplane
5424         p->materialflags |= t->currentmaterialflags;
5425         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5426         {
5427                 // merge this surface's PVS into the waterplane
5428                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5429                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5430                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5431                 {
5432                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5433                         p->pvsvalid = true;
5434                 }
5435         }
5436 }
5437
5438 static void R_Water_ProcessPlanes(void)
5439 {
5440         int myscissor[4];
5441         r_refdef_view_t originalview;
5442         r_refdef_view_t myview;
5443         int planeindex;
5444         r_waterstate_waterplane_t *p;
5445         vec3_t visorigin;
5446
5447         originalview = r_refdef.view;
5448
5449         // make sure enough textures are allocated
5450         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5451         {
5452                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5453                 {
5454                         if (!p->texture_refraction)
5455                                 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);
5456                         if (!p->texture_refraction)
5457                                 goto error;
5458                 }
5459                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5460                 {
5461                         if (!p->texture_camera)
5462                                 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);
5463                         if (!p->texture_camera)
5464                                 goto error;
5465                 }
5466
5467                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5468                 {
5469                         if (!p->texture_reflection)
5470                                 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);
5471                         if (!p->texture_reflection)
5472                                 goto error;
5473                 }
5474         }
5475
5476         // render views
5477         r_refdef.view = originalview;
5478         r_refdef.view.showdebug = false;
5479         r_refdef.view.width = r_waterstate.waterwidth;
5480         r_refdef.view.height = r_waterstate.waterheight;
5481         r_refdef.view.useclipplane = true;
5482         myview = r_refdef.view;
5483         r_waterstate.renderingscene = true;
5484         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5485         {
5486                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5487                 {
5488                         r_refdef.view = myview;
5489                         if(r_water_scissormode.integer)
5490                         {
5491                                 R_SetupView(true);
5492                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5493                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5494                         }
5495
5496                         // render reflected scene and copy into texture
5497                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5498                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5499                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5500                         r_refdef.view.clipplane = p->plane;
5501
5502                         // reverse the cullface settings for this render
5503                         r_refdef.view.cullface_front = GL_FRONT;
5504                         r_refdef.view.cullface_back = GL_BACK;
5505                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5506                         {
5507                                 r_refdef.view.usecustompvs = true;
5508                                 if (p->pvsvalid)
5509                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5510                                 else
5511                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5512                         }
5513
5514                         R_ResetViewRendering3D();
5515                         R_ClearScreen(r_refdef.fogenabled);
5516                         if(r_water_scissormode.integer & 2)
5517                                 R_View_UpdateWithScissor(myscissor);
5518                         else
5519                                 R_View_Update();
5520                         if(r_water_scissormode.integer & 1)
5521                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5522                         R_RenderScene();
5523
5524                         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);
5525                 }
5526
5527                 // render the normal view scene and copy into texture
5528                 // (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)
5529                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5530                 {
5531                         r_refdef.view = myview;
5532                         if(r_water_scissormode.integer)
5533                         {
5534                                 R_SetupView(true);
5535                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5536                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5537                         }
5538
5539                         r_waterstate.renderingrefraction = true;
5540
5541                         r_refdef.view.clipplane = p->plane;
5542                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5543                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5544
5545                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5546                         {
5547                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5548                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5549                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5550                                 R_RenderView_UpdateViewVectors();
5551                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5552                                 {
5553                                         r_refdef.view.usecustompvs = true;
5554                                         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);
5555                                 }
5556                         }
5557
5558                         PlaneClassify(&r_refdef.view.clipplane);
5559
5560                         R_ResetViewRendering3D();
5561                         R_ClearScreen(r_refdef.fogenabled);
5562                         if(r_water_scissormode.integer & 2)
5563                                 R_View_UpdateWithScissor(myscissor);
5564                         else
5565                                 R_View_Update();
5566                         if(r_water_scissormode.integer & 1)
5567                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5568                         R_RenderScene();
5569
5570                         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);
5571                         r_waterstate.renderingrefraction = false;
5572                 }
5573                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5574                 {
5575                         r_refdef.view = myview;
5576
5577                         r_refdef.view.clipplane = p->plane;
5578                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5579                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5580
5581                         r_refdef.view.width = r_waterstate.camerawidth;
5582                         r_refdef.view.height = r_waterstate.cameraheight;
5583                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5584                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5585
5586                         if(p->camera_entity)
5587                         {
5588                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5589                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5590                         }
5591
5592                         // note: all of the view is used for displaying... so
5593                         // there is no use in scissoring
5594
5595                         // reverse the cullface settings for this render
5596                         r_refdef.view.cullface_front = GL_FRONT;
5597                         r_refdef.view.cullface_back = GL_BACK;
5598                         // also reverse the view matrix
5599                         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
5600                         R_RenderView_UpdateViewVectors();
5601                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5602                         {
5603                                 r_refdef.view.usecustompvs = true;
5604                                 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);
5605                         }
5606                         
5607                         // camera needs no clipplane
5608                         r_refdef.view.useclipplane = false;
5609
5610                         PlaneClassify(&r_refdef.view.clipplane);
5611
5612                         R_ResetViewRendering3D();
5613                         R_ClearScreen(r_refdef.fogenabled);
5614                         R_View_Update();
5615                         R_RenderScene();
5616
5617                         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);
5618                         r_waterstate.renderingrefraction = false;
5619                 }
5620
5621         }
5622         r_waterstate.renderingscene = false;
5623         r_refdef.view = originalview;
5624         R_ResetViewRendering3D();
5625         R_ClearScreen(r_refdef.fogenabled);
5626         R_View_Update();
5627         return;
5628 error:
5629         r_refdef.view = originalview;
5630         r_waterstate.renderingscene = false;
5631         Cvar_SetValueQuick(&r_water, 0);
5632         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5633         return;
5634 }
5635
5636 void R_Bloom_StartFrame(void)
5637 {
5638         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5639
5640         switch(vid.renderpath)
5641         {
5642         case RENDERPATH_GL20:
5643         case RENDERPATH_D3D9:
5644         case RENDERPATH_D3D10:
5645         case RENDERPATH_D3D11:
5646         case RENDERPATH_SOFT:
5647         case RENDERPATH_GLES2:
5648                 break;
5649         case RENDERPATH_GL13:
5650         case RENDERPATH_GL11:
5651                 return;
5652         }
5653
5654         // set bloomwidth and bloomheight to the bloom resolution that will be
5655         // used (often less than the screen resolution for faster rendering)
5656         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5657         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5658         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5659         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5660         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5661
5662         // calculate desired texture sizes
5663         if (vid.support.arb_texture_non_power_of_two)
5664         {
5665                 screentexturewidth = r_refdef.view.width;
5666                 screentextureheight = r_refdef.view.height;
5667                 bloomtexturewidth = r_bloomstate.bloomwidth;
5668                 bloomtextureheight = r_bloomstate.bloomheight;
5669         }
5670         else
5671         {
5672                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5673                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5674                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5675                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5676         }
5677
5678         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))
5679         {
5680                 Cvar_SetValueQuick(&r_hdr, 0);
5681                 Cvar_SetValueQuick(&r_bloom, 0);
5682                 Cvar_SetValueQuick(&r_motionblur, 0);
5683                 Cvar_SetValueQuick(&r_damageblur, 0);
5684         }
5685
5686         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)))
5687                 screentexturewidth = screentextureheight = 0;
5688         if (!r_hdr.integer && !r_bloom.integer)
5689                 bloomtexturewidth = bloomtextureheight = 0;
5690
5691         // allocate textures as needed
5692         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5693         {
5694                 if (r_bloomstate.texture_screen)
5695                         R_FreeTexture(r_bloomstate.texture_screen);
5696                 r_bloomstate.texture_screen = NULL;
5697                 r_bloomstate.screentexturewidth = screentexturewidth;
5698                 r_bloomstate.screentextureheight = screentextureheight;
5699                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5700                         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);
5701         }
5702         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5703         {
5704                 if (r_bloomstate.texture_bloom)
5705                         R_FreeTexture(r_bloomstate.texture_bloom);
5706                 r_bloomstate.texture_bloom = NULL;
5707                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5708                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5709                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5710                         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);
5711         }
5712
5713         // when doing a reduced render (HDR) we want to use a smaller area
5714         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5715         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5716         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5717         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5718         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5719
5720         // set up a texcoord array for the full resolution screen image
5721         // (we have to keep this around to copy back during final render)
5722         r_bloomstate.screentexcoord2f[0] = 0;
5723         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5724         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5725         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5726         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5727         r_bloomstate.screentexcoord2f[5] = 0;
5728         r_bloomstate.screentexcoord2f[6] = 0;
5729         r_bloomstate.screentexcoord2f[7] = 0;
5730
5731         // set up a texcoord array for the reduced resolution bloom image
5732         // (which will be additive blended over the screen image)
5733         r_bloomstate.bloomtexcoord2f[0] = 0;
5734         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5735         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5736         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5737         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5738         r_bloomstate.bloomtexcoord2f[5] = 0;
5739         r_bloomstate.bloomtexcoord2f[6] = 0;
5740         r_bloomstate.bloomtexcoord2f[7] = 0;
5741
5742         switch(vid.renderpath)
5743         {
5744         case RENDERPATH_GL11:
5745         case RENDERPATH_GL13:
5746         case RENDERPATH_GL20:
5747         case RENDERPATH_SOFT:
5748         case RENDERPATH_GLES2:
5749                 break;
5750         case RENDERPATH_D3D9:
5751         case RENDERPATH_D3D10:
5752         case RENDERPATH_D3D11:
5753                 {
5754                         int i;
5755                         for (i = 0;i < 4;i++)
5756                         {
5757                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5758                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5759                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5760                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5761                         }
5762                 }
5763                 break;
5764         }
5765
5766         if (r_hdr.integer || r_bloom.integer)
5767         {
5768                 r_bloomstate.enabled = true;
5769                 r_bloomstate.hdr = r_hdr.integer != 0;
5770         }
5771
5772         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);
5773 }
5774
5775 void R_Bloom_CopyBloomTexture(float colorscale)
5776 {
5777         r_refdef.stats.bloom++;
5778
5779         // scale down screen texture to the bloom texture size
5780         CHECKGLERROR
5781         R_SetViewport(&r_bloomstate.viewport);
5782         GL_BlendFunc(GL_ONE, GL_ZERO);
5783         GL_Color(colorscale, colorscale, colorscale, 1);
5784         // 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...
5785         switch(vid.renderpath)
5786         {
5787         case RENDERPATH_GL11:
5788         case RENDERPATH_GL13:
5789         case RENDERPATH_GL20:
5790         case RENDERPATH_SOFT:
5791         case RENDERPATH_GLES2:
5792                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5793                 break;
5794         case RENDERPATH_D3D9:
5795         case RENDERPATH_D3D10:
5796         case RENDERPATH_D3D11:
5797                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5798                 break;
5799         }
5800         // TODO: do boxfilter scale-down in shader?
5801         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5802         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5803         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5804
5805         // we now have a bloom image in the framebuffer
5806         // copy it into the bloom image texture for later processing
5807         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);
5808         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5809 }
5810
5811 void R_Bloom_CopyHDRTexture(void)
5812 {
5813         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);
5814         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5815 }
5816
5817 void R_Bloom_MakeTexture(void)
5818 {
5819         int x, range, dir;
5820         float xoffset, yoffset, r, brighten;
5821
5822         r_refdef.stats.bloom++;
5823
5824         R_ResetViewRendering2D();
5825
5826         // we have a bloom image in the framebuffer
5827         CHECKGLERROR
5828         R_SetViewport(&r_bloomstate.viewport);
5829
5830         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5831         {
5832                 x *= 2;
5833                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5834                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5835                 GL_Color(r,r,r,1);
5836                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5837                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5838                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5839                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5840
5841                 // copy the vertically blurred bloom view to a texture
5842                 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);
5843                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5844         }
5845
5846         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5847         brighten = r_bloom_brighten.value;
5848         if (r_hdr.integer)
5849                 brighten *= r_hdr_range.value;
5850         brighten = sqrt(brighten);
5851         if(range >= 1)
5852                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5853         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5854
5855         for (dir = 0;dir < 2;dir++)
5856         {
5857                 // blend on at multiple vertical offsets to achieve a vertical blur
5858                 // TODO: do offset blends using GLSL
5859                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5860                 GL_BlendFunc(GL_ONE, GL_ZERO);
5861                 for (x = -range;x <= range;x++)
5862                 {
5863                         if (!dir){xoffset = 0;yoffset = x;}
5864                         else {xoffset = x;yoffset = 0;}
5865                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5866                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5867                         // compute a texcoord array with the specified x and y offset
5868                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5869                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5870                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5871                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5872                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5873                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5874                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5875                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5876                         // this r value looks like a 'dot' particle, fading sharply to
5877                         // black at the edges
5878                         // (probably not realistic but looks good enough)
5879                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5880                         //r = brighten/(range*2+1);
5881                         r = brighten / (range * 2 + 1);
5882                         if(range >= 1)
5883                                 r *= (1 - x*x/(float)(range*range));
5884                         GL_Color(r, r, r, 1);
5885                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5886                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5887                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5888                         GL_BlendFunc(GL_ONE, GL_ONE);
5889                 }
5890
5891                 // copy the vertically blurred bloom view to a texture
5892                 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);
5893                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5894         }
5895 }
5896
5897 void R_HDR_RenderBloomTexture(void)
5898 {
5899         int oldwidth, oldheight;
5900         float oldcolorscale;
5901         qboolean oldwaterstate;
5902
5903         oldwaterstate = r_waterstate.enabled;
5904         oldcolorscale = r_refdef.view.colorscale;
5905         oldwidth = r_refdef.view.width;
5906         oldheight = r_refdef.view.height;
5907         r_refdef.view.width = r_bloomstate.bloomwidth;
5908         r_refdef.view.height = r_bloomstate.bloomheight;
5909
5910         if(r_hdr.integer < 2)
5911                 r_waterstate.enabled = false;
5912
5913         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5914         // TODO: add exposure compensation features
5915         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5916
5917         r_refdef.view.showdebug = false;
5918         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5919
5920         R_ResetViewRendering3D();
5921
5922         R_ClearScreen(r_refdef.fogenabled);
5923         if (r_timereport_active)
5924                 R_TimeReport("HDRclear");
5925
5926         R_View_Update();
5927         if (r_timereport_active)
5928                 R_TimeReport("visibility");
5929
5930         // only do secondary renders with HDR if r_hdr is 2 or higher
5931         r_waterstate.numwaterplanes = 0;
5932         if (r_waterstate.enabled)
5933                 R_RenderWaterPlanes();
5934
5935         r_refdef.view.showdebug = true;
5936         R_RenderScene();
5937         r_waterstate.numwaterplanes = 0;
5938
5939         R_ResetViewRendering2D();
5940
5941         R_Bloom_CopyHDRTexture();
5942         R_Bloom_MakeTexture();
5943
5944         // restore the view settings
5945         r_waterstate.enabled = oldwaterstate;
5946         r_refdef.view.width = oldwidth;
5947         r_refdef.view.height = oldheight;
5948         r_refdef.view.colorscale = oldcolorscale;
5949
5950         R_ResetViewRendering3D();
5951
5952         R_ClearScreen(r_refdef.fogenabled);
5953         if (r_timereport_active)
5954                 R_TimeReport("viewclear");
5955 }
5956
5957 static void R_BlendView(void)
5958 {
5959         unsigned int permutation;
5960         float uservecs[4][4];
5961
5962         switch (vid.renderpath)
5963         {
5964         case RENDERPATH_GL20:
5965         case RENDERPATH_D3D9:
5966         case RENDERPATH_D3D10:
5967         case RENDERPATH_D3D11:
5968         case RENDERPATH_SOFT:
5969         case RENDERPATH_GLES2:
5970                 permutation =
5971                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5972                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5973                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5974                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5975                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5976
5977                 if (r_bloomstate.texture_screen)
5978                 {
5979                         // make sure the buffer is available
5980                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5981
5982                         R_ResetViewRendering2D();
5983
5984                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5985                         {
5986                                 // declare variables
5987                                 float speed;
5988                                 static float avgspeed;
5989
5990                                 speed = VectorLength(cl.movement_velocity);
5991
5992                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5993                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5994
5995                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5996                                 speed = bound(0, speed, 1);
5997                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5998
5999                                 // calculate values into a standard alpha
6000                                 cl.motionbluralpha = 1 - exp(-
6001                                                 (
6002                                                  (r_motionblur.value * speed / 80)
6003                                                  +
6004                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6005                                                 )
6006                                                 /
6007                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6008                                            );
6009
6010                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6011                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6012                                 // apply the blur
6013                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6014                                 {
6015                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6016                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6017                                         switch(vid.renderpath)
6018                                         {
6019                                         case RENDERPATH_GL11:
6020                                         case RENDERPATH_GL13:
6021                                         case RENDERPATH_GL20:
6022                                         case RENDERPATH_SOFT:
6023                                         case RENDERPATH_GLES2:
6024                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6025                                                 break;
6026                                         case RENDERPATH_D3D9:
6027                                         case RENDERPATH_D3D10:
6028                                         case RENDERPATH_D3D11:
6029                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6030                                                 break;
6031                                         }
6032                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6033                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6034                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6035                                 }
6036                         }
6037
6038                         // copy view into the screen texture
6039                         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);
6040                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6041                 }
6042                 else if (!r_bloomstate.texture_bloom)
6043                 {
6044                         // we may still have to do view tint...
6045                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6046                         {
6047                                 // apply a color tint to the whole view
6048                                 R_ResetViewRendering2D();
6049                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6050                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6051                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6052                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6053                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6054                         }
6055                         break; // no screen processing, no bloom, skip it
6056                 }
6057
6058                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6059                 {
6060                         // render simple bloom effect
6061                         // copy the screen and shrink it and darken it for the bloom process
6062                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6063                         // make the bloom texture
6064                         R_Bloom_MakeTexture();
6065                 }
6066
6067 #if _MSC_VER >= 1400
6068 #define sscanf sscanf_s
6069 #endif
6070                 memset(uservecs, 0, sizeof(uservecs));
6071                 if (r_glsl_postprocess_uservec1_enable.integer)
6072                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6073                 if (r_glsl_postprocess_uservec2_enable.integer)
6074                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6075                 if (r_glsl_postprocess_uservec3_enable.integer)
6076                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6077                 if (r_glsl_postprocess_uservec4_enable.integer)
6078                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6079
6080                 R_ResetViewRendering2D();
6081                 GL_Color(1, 1, 1, 1);
6082                 GL_BlendFunc(GL_ONE, GL_ZERO);
6083
6084                 switch(vid.renderpath)
6085                 {
6086                 case RENDERPATH_GL20:
6087                 case RENDERPATH_GLES2:
6088                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6089                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6090                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6091                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6092                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6093                         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]);
6094                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6095                         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]);
6096                         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]);
6097                         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]);
6098                         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]);
6099                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6100                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6101                         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);
6102                         break;
6103                 case RENDERPATH_D3D9:
6104 #ifdef SUPPORTD3D
6105                         // 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...
6106                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6107                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6108                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6109                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6110                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6111                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6112                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6113                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6114                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6115                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6116                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6117                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6118                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6119                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6120 #endif
6121                         break;
6122                 case RENDERPATH_D3D10:
6123                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6124                         break;
6125                 case RENDERPATH_D3D11:
6126                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6127                         break;
6128                 case RENDERPATH_SOFT:
6129                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6130                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6131                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6132                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6133                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6134                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6135                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6136                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6137                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6138                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6139                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6140                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6141                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6142                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6143                         break;
6144                 default:
6145                         break;
6146                 }
6147                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6148                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6149                 break;
6150         case RENDERPATH_GL13:
6151         case RENDERPATH_GL11:
6152                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6153                 {
6154                         // apply a color tint to the whole view
6155                         R_ResetViewRendering2D();
6156                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6157                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6158                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6159                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6160                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6161                 }
6162                 break;
6163         }
6164 }
6165
6166 matrix4x4_t r_waterscrollmatrix;
6167
6168 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6169 {
6170         if (r_refdef.fog_density)
6171         {
6172                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6173                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6174                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6175
6176                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6177                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6178                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6179                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6180
6181                 {
6182                         vec3_t fogvec;
6183                         VectorCopy(r_refdef.fogcolor, fogvec);
6184                         //   color.rgb *= ContrastBoost * SceneBrightness;
6185                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6186                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6187                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6188                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6189                 }
6190         }
6191 }
6192
6193 void R_UpdateVariables(void)
6194 {
6195         R_Textures_Frame();
6196
6197         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6198
6199         r_refdef.farclip = r_farclip_base.value;
6200         if (r_refdef.scene.worldmodel)
6201                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6202         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6203
6204         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6205                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6206         r_refdef.polygonfactor = 0;
6207         r_refdef.polygonoffset = 0;
6208         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6209         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6210
6211         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6212         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6213         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6214         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6215         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6216         if (FAKELIGHT_ENABLED)
6217         {
6218                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6219         }
6220         if (r_showsurfaces.integer)
6221         {
6222                 r_refdef.scene.rtworld = false;
6223                 r_refdef.scene.rtworldshadows = false;
6224                 r_refdef.scene.rtdlight = false;
6225                 r_refdef.scene.rtdlightshadows = false;
6226                 r_refdef.lightmapintensity = 0;
6227         }
6228
6229         if (gamemode == GAME_NEHAHRA)
6230         {
6231                 if (gl_fogenable.integer)
6232                 {
6233                         r_refdef.oldgl_fogenable = true;
6234                         r_refdef.fog_density = gl_fogdensity.value;
6235                         r_refdef.fog_red = gl_fogred.value;
6236                         r_refdef.fog_green = gl_foggreen.value;
6237                         r_refdef.fog_blue = gl_fogblue.value;
6238                         r_refdef.fog_alpha = 1;
6239                         r_refdef.fog_start = 0;
6240                         r_refdef.fog_end = gl_skyclip.value;
6241                         r_refdef.fog_height = 1<<30;
6242                         r_refdef.fog_fadedepth = 128;
6243                 }
6244                 else if (r_refdef.oldgl_fogenable)
6245                 {
6246                         r_refdef.oldgl_fogenable = false;
6247                         r_refdef.fog_density = 0;
6248                         r_refdef.fog_red = 0;
6249                         r_refdef.fog_green = 0;
6250                         r_refdef.fog_blue = 0;
6251                         r_refdef.fog_alpha = 0;
6252                         r_refdef.fog_start = 0;
6253                         r_refdef.fog_end = 0;
6254                         r_refdef.fog_height = 1<<30;
6255                         r_refdef.fog_fadedepth = 128;
6256                 }
6257         }
6258
6259         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6260         r_refdef.fog_start = max(0, r_refdef.fog_start);
6261         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6262
6263         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6264
6265         if (r_refdef.fog_density && r_drawfog.integer)
6266         {
6267                 r_refdef.fogenabled = true;
6268                 // this is the point where the fog reaches 0.9986 alpha, which we
6269                 // consider a good enough cutoff point for the texture
6270                 // (0.9986 * 256 == 255.6)
6271                 if (r_fog_exp2.integer)
6272                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6273                 else
6274                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6275                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6276                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6277                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6278                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6279                         R_BuildFogHeightTexture();
6280                 // fog color was already set
6281                 // update the fog texture
6282                 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)
6283                         R_BuildFogTexture();
6284                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6285                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6286         }
6287         else
6288                 r_refdef.fogenabled = false;
6289
6290         switch(vid.renderpath)
6291         {
6292         case RENDERPATH_GL20:
6293         case RENDERPATH_D3D9:
6294         case RENDERPATH_D3D10:
6295         case RENDERPATH_D3D11:
6296         case RENDERPATH_SOFT:
6297         case RENDERPATH_GLES2:
6298                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6299                 {
6300                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6301                         {
6302                                 // build GLSL gamma texture
6303 #define RAMPWIDTH 256
6304                                 unsigned short ramp[RAMPWIDTH * 3];
6305                                 unsigned char rampbgr[RAMPWIDTH][4];
6306                                 int i;
6307
6308                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6309
6310                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6311                                 for(i = 0; i < RAMPWIDTH; ++i)
6312                                 {
6313                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6314                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6315                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6316                                         rampbgr[i][3] = 0;
6317                                 }
6318                                 if (r_texture_gammaramps)
6319                                 {
6320                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6321                                 }
6322                                 else
6323                                 {
6324                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6325                                 }
6326                         }
6327                 }
6328                 else
6329                 {
6330                         // remove GLSL gamma texture
6331                 }
6332                 break;
6333         case RENDERPATH_GL13:
6334         case RENDERPATH_GL11:
6335                 break;
6336         }
6337 }
6338
6339 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6340 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6341 /*
6342 ================
6343 R_SelectScene
6344 ================
6345 */
6346 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6347         if( scenetype != r_currentscenetype ) {
6348                 // store the old scenetype
6349                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6350                 r_currentscenetype = scenetype;
6351                 // move in the new scene
6352                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6353         }
6354 }
6355
6356 /*
6357 ================
6358 R_GetScenePointer
6359 ================
6360 */
6361 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6362 {
6363         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6364         if( scenetype == r_currentscenetype ) {
6365                 return &r_refdef.scene;
6366         } else {
6367                 return &r_scenes_store[ scenetype ];
6368         }
6369 }
6370
6371 /*
6372 ================
6373 R_RenderView
6374 ================
6375 */
6376 int dpsoftrast_test;
6377 void R_RenderView(void)
6378 {
6379         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6380
6381         dpsoftrast_test = r_test.integer;
6382
6383         if (r_timereport_active)
6384                 R_TimeReport("start");
6385         r_textureframe++; // used only by R_GetCurrentTexture
6386         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6387
6388         if(R_CompileShader_CheckStaticParms())
6389                 R_GLSL_Restart_f();
6390
6391         if (!r_drawentities.integer)
6392                 r_refdef.scene.numentities = 0;
6393
6394         R_AnimCache_ClearCache();
6395         R_FrameData_NewFrame();
6396
6397         /* adjust for stereo display */
6398         if(R_Stereo_Active())
6399         {
6400                 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);
6401                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6402         }
6403
6404         if (r_refdef.view.isoverlay)
6405         {
6406                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6407                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6408                 R_TimeReport("depthclear");
6409
6410                 r_refdef.view.showdebug = false;
6411
6412                 r_waterstate.enabled = false;
6413                 r_waterstate.numwaterplanes = 0;
6414
6415                 R_RenderScene();
6416
6417                 r_refdef.view.matrix = originalmatrix;
6418
6419                 CHECKGLERROR
6420                 return;
6421         }
6422
6423         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6424         {
6425                 r_refdef.view.matrix = originalmatrix;
6426                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6427         }
6428
6429         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6430
6431         R_RenderView_UpdateViewVectors();
6432
6433         R_Shadow_UpdateWorldLightSelection();
6434
6435         R_Bloom_StartFrame();
6436         R_Water_StartFrame();
6437
6438         CHECKGLERROR
6439         if (r_timereport_active)
6440                 R_TimeReport("viewsetup");
6441
6442         R_ResetViewRendering3D();
6443
6444         if (r_refdef.view.clear || r_refdef.fogenabled)
6445         {
6446                 R_ClearScreen(r_refdef.fogenabled);
6447                 if (r_timereport_active)
6448                         R_TimeReport("viewclear");
6449         }
6450         r_refdef.view.clear = true;
6451
6452         // this produces a bloom texture to be used in R_BlendView() later
6453         if (r_hdr.integer && r_bloomstate.bloomwidth)
6454         {
6455                 R_HDR_RenderBloomTexture();
6456                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6457                 r_textureframe++; // used only by R_GetCurrentTexture
6458         }
6459
6460         r_refdef.view.showdebug = true;
6461
6462         R_View_Update();
6463         if (r_timereport_active)
6464                 R_TimeReport("visibility");
6465
6466         r_waterstate.numwaterplanes = 0;
6467         if (r_waterstate.enabled)
6468                 R_RenderWaterPlanes();
6469
6470         R_RenderScene();
6471         r_waterstate.numwaterplanes = 0;
6472
6473         R_BlendView();
6474         if (r_timereport_active)
6475                 R_TimeReport("blendview");
6476
6477         GL_Scissor(0, 0, vid.width, vid.height);
6478         GL_ScissorTest(false);
6479
6480         r_refdef.view.matrix = originalmatrix;
6481
6482         CHECKGLERROR
6483 }
6484
6485 void R_RenderWaterPlanes(void)
6486 {
6487         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6488         {
6489                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6490                 if (r_timereport_active)
6491                         R_TimeReport("waterworld");
6492         }
6493
6494         // don't let sound skip if going slow
6495         if (r_refdef.scene.extraupdate)
6496                 S_ExtraUpdate ();
6497
6498         R_DrawModelsAddWaterPlanes();
6499         if (r_timereport_active)
6500                 R_TimeReport("watermodels");
6501
6502         if (r_waterstate.numwaterplanes)
6503         {
6504                 R_Water_ProcessPlanes();
6505                 if (r_timereport_active)
6506                         R_TimeReport("waterscenes");
6507         }
6508 }
6509
6510 extern void R_DrawLightningBeams (void);
6511 extern void VM_CL_AddPolygonsToMeshQueue (void);
6512 extern void R_DrawPortals (void);
6513 extern cvar_t cl_locs_show;
6514 static void R_DrawLocs(void);
6515 static void R_DrawEntityBBoxes(void);
6516 static void R_DrawModelDecals(void);
6517 extern void R_DrawModelShadows(void);
6518 extern void R_DrawModelShadowMaps(void);
6519 extern cvar_t cl_decals_newsystem;
6520 extern qboolean r_shadow_usingdeferredprepass;
6521 void R_RenderScene(void)
6522 {
6523         qboolean shadowmapping = false;
6524
6525         if (r_timereport_active)
6526                 R_TimeReport("beginscene");
6527
6528         r_refdef.stats.renders++;
6529
6530         R_UpdateFogColor();
6531
6532         // don't let sound skip if going slow
6533         if (r_refdef.scene.extraupdate)
6534                 S_ExtraUpdate ();
6535
6536         R_MeshQueue_BeginScene();
6537
6538         R_SkyStartFrame();
6539
6540         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);
6541
6542         if (r_timereport_active)
6543                 R_TimeReport("skystartframe");
6544
6545         if (cl.csqc_vidvars.drawworld)
6546         {
6547                 // don't let sound skip if going slow
6548                 if (r_refdef.scene.extraupdate)
6549                         S_ExtraUpdate ();
6550
6551                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6552                 {
6553                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6554                         if (r_timereport_active)
6555                                 R_TimeReport("worldsky");
6556                 }
6557
6558                 if (R_DrawBrushModelsSky() && r_timereport_active)
6559                         R_TimeReport("bmodelsky");
6560
6561                 if (skyrendermasked && skyrenderlater)
6562                 {
6563                         // we have to force off the water clipping plane while rendering sky
6564                         R_SetupView(false);
6565                         R_Sky();
6566                         R_SetupView(true);
6567                         if (r_timereport_active)
6568                                 R_TimeReport("sky");
6569                 }
6570         }
6571
6572         R_AnimCache_CacheVisibleEntities();
6573         if (r_timereport_active)
6574                 R_TimeReport("animation");
6575
6576         R_Shadow_PrepareLights();
6577         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6578                 R_Shadow_PrepareModelShadows();
6579         if (r_timereport_active)
6580                 R_TimeReport("preparelights");
6581
6582         if (R_Shadow_ShadowMappingEnabled())
6583                 shadowmapping = true;
6584
6585         if (r_shadow_usingdeferredprepass)
6586                 R_Shadow_DrawPrepass();
6587
6588         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6589         {
6590                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6591                 if (r_timereport_active)
6592                         R_TimeReport("worlddepth");
6593         }
6594         if (r_depthfirst.integer >= 2)
6595         {
6596                 R_DrawModelsDepth();
6597                 if (r_timereport_active)
6598                         R_TimeReport("modeldepth");
6599         }
6600
6601         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6602         {
6603                 R_DrawModelShadowMaps();
6604                 R_ResetViewRendering3D();
6605                 // don't let sound skip if going slow
6606                 if (r_refdef.scene.extraupdate)
6607                         S_ExtraUpdate ();
6608         }
6609
6610         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6611         {
6612                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6613                 if (r_timereport_active)
6614                         R_TimeReport("world");
6615         }
6616
6617         // don't let sound skip if going slow
6618         if (r_refdef.scene.extraupdate)
6619                 S_ExtraUpdate ();
6620
6621         R_DrawModels();
6622         if (r_timereport_active)
6623                 R_TimeReport("models");
6624
6625         // don't let sound skip if going slow
6626         if (r_refdef.scene.extraupdate)
6627                 S_ExtraUpdate ();
6628
6629         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6630         {
6631                 R_DrawModelShadows();
6632                 R_ResetViewRendering3D();
6633                 // don't let sound skip if going slow
6634                 if (r_refdef.scene.extraupdate)
6635                         S_ExtraUpdate ();
6636         }
6637
6638         if (!r_shadow_usingdeferredprepass)
6639         {
6640                 R_Shadow_DrawLights();
6641                 if (r_timereport_active)
6642                         R_TimeReport("rtlights");
6643         }
6644
6645         // don't let sound skip if going slow
6646         if (r_refdef.scene.extraupdate)
6647                 S_ExtraUpdate ();
6648
6649         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6650         {
6651                 R_DrawModelShadows();
6652                 R_ResetViewRendering3D();
6653                 // don't let sound skip if going slow
6654                 if (r_refdef.scene.extraupdate)
6655                         S_ExtraUpdate ();
6656         }
6657
6658         if (cl.csqc_vidvars.drawworld)
6659         {
6660                 if (cl_decals_newsystem.integer)
6661                 {
6662                         R_DrawModelDecals();
6663                         if (r_timereport_active)
6664                                 R_TimeReport("modeldecals");
6665                 }
6666                 else
6667                 {
6668                         R_DrawDecals();
6669                         if (r_timereport_active)
6670                                 R_TimeReport("decals");
6671                 }
6672
6673                 R_DrawParticles();
6674                 if (r_timereport_active)
6675                         R_TimeReport("particles");
6676
6677                 R_DrawExplosions();
6678                 if (r_timereport_active)
6679                         R_TimeReport("explosions");
6680
6681                 R_DrawLightningBeams();
6682                 if (r_timereport_active)
6683                         R_TimeReport("lightning");
6684         }
6685
6686         VM_CL_AddPolygonsToMeshQueue();
6687
6688         if (r_refdef.view.showdebug)
6689         {
6690                 if (cl_locs_show.integer)
6691                 {
6692                         R_DrawLocs();
6693                         if (r_timereport_active)
6694                                 R_TimeReport("showlocs");
6695                 }
6696
6697                 if (r_drawportals.integer)
6698                 {
6699                         R_DrawPortals();
6700                         if (r_timereport_active)
6701                                 R_TimeReport("portals");
6702                 }
6703
6704                 if (r_showbboxes.value > 0)
6705                 {
6706                         R_DrawEntityBBoxes();
6707                         if (r_timereport_active)
6708                                 R_TimeReport("bboxes");
6709                 }
6710         }
6711
6712         R_MeshQueue_RenderTransparent();
6713         if (r_timereport_active)
6714                 R_TimeReport("drawtrans");
6715
6716         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))
6717         {
6718                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6719                 if (r_timereport_active)
6720                         R_TimeReport("worlddebug");
6721                 R_DrawModelsDebug();
6722                 if (r_timereport_active)
6723                         R_TimeReport("modeldebug");
6724         }
6725
6726         if (cl.csqc_vidvars.drawworld)
6727         {
6728                 R_Shadow_DrawCoronas();
6729                 if (r_timereport_active)
6730                         R_TimeReport("coronas");
6731         }
6732
6733 #if 0
6734         {
6735                 GL_DepthTest(false);
6736                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6737                 GL_Color(1, 1, 1, 1);
6738                 qglBegin(GL_POLYGON);
6739                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6740                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6741                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6742                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6743                 qglEnd();
6744                 qglBegin(GL_POLYGON);
6745                 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]);
6746                 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]);
6747                 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]);
6748                 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]);
6749                 qglEnd();
6750                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6751         }
6752 #endif
6753
6754         // don't let sound skip if going slow
6755         if (r_refdef.scene.extraupdate)
6756                 S_ExtraUpdate ();
6757
6758         R_ResetViewRendering2D();
6759 }
6760
6761 static const unsigned short bboxelements[36] =
6762 {
6763         5, 1, 3, 5, 3, 7,
6764         6, 2, 0, 6, 0, 4,
6765         7, 3, 2, 7, 2, 6,
6766         4, 0, 1, 4, 1, 5,
6767         4, 5, 7, 4, 7, 6,
6768         1, 0, 2, 1, 2, 3,
6769 };
6770
6771 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6772 {
6773         int i;
6774         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6775
6776         RSurf_ActiveWorldEntity();
6777
6778         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6779         GL_DepthMask(false);
6780         GL_DepthRange(0, 1);
6781         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6782 //      R_Mesh_ResetTextureState();
6783
6784         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6785         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6786         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6787         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6788         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6789         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6790         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6791         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6792         R_FillColors(color4f, 8, cr, cg, cb, ca);
6793         if (r_refdef.fogenabled)
6794         {
6795                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6796                 {
6797                         f1 = RSurf_FogVertex(v);
6798                         f2 = 1 - f1;
6799                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6800                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6801                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6802                 }
6803         }
6804         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6805         R_Mesh_ResetTextureState();
6806         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6807         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6808 }
6809
6810 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6811 {
6812         int i;
6813         float color[4];
6814         prvm_edict_t *edict;
6815         prvm_prog_t *prog_save = prog;
6816
6817         // this function draws bounding boxes of server entities
6818         if (!sv.active)
6819                 return;
6820
6821         GL_CullFace(GL_NONE);
6822         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6823
6824         prog = 0;
6825         SV_VM_Begin();
6826         for (i = 0;i < numsurfaces;i++)
6827         {
6828                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6829                 switch ((int)edict->fields.server->solid)
6830                 {
6831                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6832                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6833                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6834                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6835                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6836                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6837                 }
6838                 color[3] *= r_showbboxes.value;
6839                 color[3] = bound(0, color[3], 1);
6840                 GL_DepthTest(!r_showdisabledepthtest.integer);
6841                 GL_CullFace(r_refdef.view.cullface_front);
6842                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6843         }
6844         SV_VM_End();
6845         prog = prog_save;
6846 }
6847
6848 static void R_DrawEntityBBoxes(void)
6849 {
6850         int i;
6851         prvm_edict_t *edict;
6852         vec3_t center;
6853         prvm_prog_t *prog_save = prog;
6854
6855         // this function draws bounding boxes of server entities
6856         if (!sv.active)
6857                 return;
6858
6859         prog = 0;
6860         SV_VM_Begin();
6861         for (i = 0;i < prog->num_edicts;i++)
6862         {
6863                 edict = PRVM_EDICT_NUM(i);
6864                 if (edict->priv.server->free)
6865                         continue;
6866                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6867                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6868                         continue;
6869                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6870                         continue;
6871                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6872                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6873         }
6874         SV_VM_End();
6875         prog = prog_save;
6876 }
6877
6878 static const int nomodelelement3i[24] =
6879 {
6880         5, 2, 0,
6881         5, 1, 2,
6882         5, 0, 3,
6883         5, 3, 1,
6884         0, 2, 4,
6885         2, 1, 4,
6886         3, 0, 4,
6887         1, 3, 4
6888 };
6889
6890 static const unsigned short nomodelelement3s[24] =
6891 {
6892         5, 2, 0,
6893         5, 1, 2,
6894         5, 0, 3,
6895         5, 3, 1,
6896         0, 2, 4,
6897         2, 1, 4,
6898         3, 0, 4,
6899         1, 3, 4
6900 };
6901
6902 static const float nomodelvertex3f[6*3] =
6903 {
6904         -16,   0,   0,
6905          16,   0,   0,
6906           0, -16,   0,
6907           0,  16,   0,
6908           0,   0, -16,
6909           0,   0,  16
6910 };
6911
6912 static const float nomodelcolor4f[6*4] =
6913 {
6914         0.0f, 0.0f, 0.5f, 1.0f,
6915         0.0f, 0.0f, 0.5f, 1.0f,
6916         0.0f, 0.5f, 0.0f, 1.0f,
6917         0.0f, 0.5f, 0.0f, 1.0f,
6918         0.5f, 0.0f, 0.0f, 1.0f,
6919         0.5f, 0.0f, 0.0f, 1.0f
6920 };
6921
6922 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6923 {
6924         int i;
6925         float f1, f2, *c;
6926         float color4f[6*4];
6927
6928         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);
6929
6930         // this is only called once per entity so numsurfaces is always 1, and
6931         // surfacelist is always {0}, so this code does not handle batches
6932
6933         if (rsurface.ent_flags & RENDER_ADDITIVE)
6934         {
6935                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6936                 GL_DepthMask(false);
6937         }
6938         else if (rsurface.colormod[3] < 1)
6939         {
6940                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6941                 GL_DepthMask(false);
6942         }
6943         else
6944         {
6945                 GL_BlendFunc(GL_ONE, GL_ZERO);
6946                 GL_DepthMask(true);
6947         }
6948         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6949         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6950         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6951         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6952         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6953         for (i = 0, c = color4f;i < 6;i++, c += 4)
6954         {
6955                 c[0] *= rsurface.colormod[0];
6956                 c[1] *= rsurface.colormod[1];
6957                 c[2] *= rsurface.colormod[2];
6958                 c[3] *= rsurface.colormod[3];
6959         }
6960         if (r_refdef.fogenabled)
6961         {
6962                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6963                 {
6964                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6965                         f2 = 1 - f1;
6966                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6967                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6968                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6969                 }
6970         }
6971 //      R_Mesh_ResetTextureState();
6972         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6973         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6974         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6975 }
6976
6977 void R_DrawNoModel(entity_render_t *ent)
6978 {
6979         vec3_t org;
6980         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6981         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6982                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6983         else
6984                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6985 }
6986
6987 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6988 {
6989         vec3_t right1, right2, diff, normal;
6990
6991         VectorSubtract (org2, org1, normal);
6992
6993         // calculate 'right' vector for start
6994         VectorSubtract (r_refdef.view.origin, org1, diff);
6995         CrossProduct (normal, diff, right1);
6996         VectorNormalize (right1);
6997
6998         // calculate 'right' vector for end
6999         VectorSubtract (r_refdef.view.origin, org2, diff);
7000         CrossProduct (normal, diff, right2);
7001         VectorNormalize (right2);
7002
7003         vert[ 0] = org1[0] + width * right1[0];
7004         vert[ 1] = org1[1] + width * right1[1];
7005         vert[ 2] = org1[2] + width * right1[2];
7006         vert[ 3] = org1[0] - width * right1[0];
7007         vert[ 4] = org1[1] - width * right1[1];
7008         vert[ 5] = org1[2] - width * right1[2];
7009         vert[ 6] = org2[0] - width * right2[0];
7010         vert[ 7] = org2[1] - width * right2[1];
7011         vert[ 8] = org2[2] - width * right2[2];
7012         vert[ 9] = org2[0] + width * right2[0];
7013         vert[10] = org2[1] + width * right2[1];
7014         vert[11] = org2[2] + width * right2[2];
7015 }
7016
7017 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)
7018 {
7019         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7020         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7021         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7022         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7023         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7024         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7025         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7026         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7027         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7028         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7029         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7030         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7031 }
7032
7033 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7034 {
7035         int i;
7036         float *vertex3f;
7037         float v[3];
7038         VectorSet(v, x, y, z);
7039         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7040                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7041                         break;
7042         if (i == mesh->numvertices)
7043         {
7044                 if (mesh->numvertices < mesh->maxvertices)
7045                 {
7046                         VectorCopy(v, vertex3f);
7047                         mesh->numvertices++;
7048                 }
7049                 return mesh->numvertices;
7050         }
7051         else
7052                 return i;
7053 }
7054
7055 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7056 {
7057         int i;
7058         int *e, element[3];
7059         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7060         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7061         e = mesh->element3i + mesh->numtriangles * 3;
7062         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7063         {
7064                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7065                 if (mesh->numtriangles < mesh->maxtriangles)
7066                 {
7067                         *e++ = element[0];
7068                         *e++ = element[1];
7069                         *e++ = element[2];
7070                         mesh->numtriangles++;
7071                 }
7072                 element[1] = element[2];
7073         }
7074 }
7075
7076 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7077 {
7078         int i;
7079         int *e, element[3];
7080         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7081         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7082         e = mesh->element3i + mesh->numtriangles * 3;
7083         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7084         {
7085                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7086                 if (mesh->numtriangles < mesh->maxtriangles)
7087                 {
7088                         *e++ = element[0];
7089                         *e++ = element[1];
7090                         *e++ = element[2];
7091                         mesh->numtriangles++;
7092                 }
7093                 element[1] = element[2];
7094         }
7095 }
7096
7097 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7098 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7099 {
7100         int planenum, planenum2;
7101         int w;
7102         int tempnumpoints;
7103         mplane_t *plane, *plane2;
7104         double maxdist;
7105         double temppoints[2][256*3];
7106         // figure out how large a bounding box we need to properly compute this brush
7107         maxdist = 0;
7108         for (w = 0;w < numplanes;w++)
7109                 maxdist = max(maxdist, fabs(planes[w].dist));
7110         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7111         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7112         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7113         {
7114                 w = 0;
7115                 tempnumpoints = 4;
7116                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7117                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7118                 {
7119                         if (planenum2 == planenum)
7120                                 continue;
7121                         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);
7122                         w = !w;
7123                 }
7124                 if (tempnumpoints < 3)
7125                         continue;
7126                 // generate elements forming a triangle fan for this polygon
7127                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7128         }
7129 }
7130
7131 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)
7132 {
7133         texturelayer_t *layer;
7134         layer = t->currentlayers + t->currentnumlayers++;
7135         layer->type = type;
7136         layer->depthmask = depthmask;
7137         layer->blendfunc1 = blendfunc1;
7138         layer->blendfunc2 = blendfunc2;
7139         layer->texture = texture;
7140         layer->texmatrix = *matrix;
7141         layer->color[0] = r;
7142         layer->color[1] = g;
7143         layer->color[2] = b;
7144         layer->color[3] = a;
7145 }
7146
7147 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7148 {
7149         if(parms[0] == 0 && parms[1] == 0)
7150                 return false;
7151         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7152                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7153                         return false;
7154         return true;
7155 }
7156
7157 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7158 {
7159         double index, f;
7160         index = parms[2] + r_refdef.scene.time * parms[3];
7161         index -= floor(index);
7162         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7163         {
7164         default:
7165         case Q3WAVEFUNC_NONE:
7166         case Q3WAVEFUNC_NOISE:
7167         case Q3WAVEFUNC_COUNT:
7168                 f = 0;
7169                 break;
7170         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7171         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7172         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7173         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7174         case Q3WAVEFUNC_TRIANGLE:
7175                 index *= 4;
7176                 f = index - floor(index);
7177                 if (index < 1)
7178                         f = f;
7179                 else if (index < 2)
7180                         f = 1 - f;
7181                 else if (index < 3)
7182                         f = -f;
7183                 else
7184                         f = -(1 - f);
7185                 break;
7186         }
7187         f = parms[0] + parms[1] * f;
7188         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7189                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7190         return (float) f;
7191 }
7192
7193 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7194 {
7195         int w, h, idx;
7196         float f;
7197         float tcmat[12];
7198         matrix4x4_t matrix, temp;
7199         switch(tcmod->tcmod)
7200         {
7201                 case Q3TCMOD_COUNT:
7202                 case Q3TCMOD_NONE:
7203                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7204                                 matrix = r_waterscrollmatrix;
7205                         else
7206                                 matrix = identitymatrix;
7207                         break;
7208                 case Q3TCMOD_ENTITYTRANSLATE:
7209                         // this is used in Q3 to allow the gamecode to control texcoord
7210                         // scrolling on the entity, which is not supported in darkplaces yet.
7211                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7212                         break;
7213                 case Q3TCMOD_ROTATE:
7214                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7215                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7216                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7217                         break;
7218                 case Q3TCMOD_SCALE:
7219                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7220                         break;
7221                 case Q3TCMOD_SCROLL:
7222                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7223                         break;
7224                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7225                         w = (int) tcmod->parms[0];
7226                         h = (int) tcmod->parms[1];
7227                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7228                         f = f - floor(f);
7229                         idx = (int) floor(f * w * h);
7230                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7231                         break;
7232                 case Q3TCMOD_STRETCH:
7233                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7234                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7235                         break;
7236                 case Q3TCMOD_TRANSFORM:
7237                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7238                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7239                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7240                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7241                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7242                         break;
7243                 case Q3TCMOD_TURBULENT:
7244                         // this is handled in the RSurf_PrepareVertices function
7245                         matrix = identitymatrix;
7246                         break;
7247         }
7248         temp = *texmatrix;
7249         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7250 }
7251
7252 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7253 {
7254         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7255         char name[MAX_QPATH];
7256         skinframe_t *skinframe;
7257         unsigned char pixels[296*194];
7258         strlcpy(cache->name, skinname, sizeof(cache->name));
7259         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7260         if (developer_loading.integer)
7261                 Con_Printf("loading %s\n", name);
7262         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7263         if (!skinframe || !skinframe->base)
7264         {
7265                 unsigned char *f;
7266                 fs_offset_t filesize;
7267                 skinframe = NULL;
7268                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7269                 if (f)
7270                 {
7271                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7272                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7273                         Mem_Free(f);
7274                 }
7275         }
7276         cache->skinframe = skinframe;
7277 }
7278
7279 texture_t *R_GetCurrentTexture(texture_t *t)
7280 {
7281         int i;
7282         const entity_render_t *ent = rsurface.entity;
7283         dp_model_t *model = ent->model;
7284         q3shaderinfo_layer_tcmod_t *tcmod;
7285
7286         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7287                 return t->currentframe;
7288         t->update_lastrenderframe = r_textureframe;
7289         t->update_lastrenderentity = (void *)ent;
7290
7291         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7292                 t->camera_entity = ent->entitynumber;
7293         else
7294                 t->camera_entity = 0;
7295
7296         // switch to an alternate material if this is a q1bsp animated material
7297         {
7298                 texture_t *texture = t;
7299                 int s = rsurface.ent_skinnum;
7300                 if ((unsigned int)s >= (unsigned int)model->numskins)
7301                         s = 0;
7302                 if (model->skinscenes)
7303                 {
7304                         if (model->skinscenes[s].framecount > 1)
7305                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7306                         else
7307                                 s = model->skinscenes[s].firstframe;
7308                 }
7309                 if (s > 0)
7310                         t = t + s * model->num_surfaces;
7311                 if (t->animated)
7312                 {
7313                         // use an alternate animation if the entity's frame is not 0,
7314                         // and only if the texture has an alternate animation
7315                         if (rsurface.ent_alttextures && t->anim_total[1])
7316                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7317                         else
7318                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7319                 }
7320                 texture->currentframe = t;
7321         }
7322
7323         // update currentskinframe to be a qw skin or animation frame
7324         if (rsurface.ent_qwskin >= 0)
7325         {
7326                 i = rsurface.ent_qwskin;
7327                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7328                 {
7329                         r_qwskincache_size = cl.maxclients;
7330                         if (r_qwskincache)
7331                                 Mem_Free(r_qwskincache);
7332                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7333                 }
7334                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7335                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7336                 t->currentskinframe = r_qwskincache[i].skinframe;
7337                 if (t->currentskinframe == NULL)
7338                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7339         }
7340         else if (t->numskinframes >= 2)
7341                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7342         if (t->backgroundnumskinframes >= 2)
7343                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7344
7345         t->currentmaterialflags = t->basematerialflags;
7346         t->currentalpha = rsurface.colormod[3];
7347         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7348                 t->currentalpha *= r_wateralpha.value;
7349         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7350                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7351         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7352                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7353         if (!(rsurface.ent_flags & RENDER_LIGHT))
7354                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7355         else if (FAKELIGHT_ENABLED)
7356         {
7357                         // no modellight if using fakelight for the map
7358         }
7359         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7360         {
7361                 // pick a model lighting mode
7362                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7363                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7364                 else
7365                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7366         }
7367         if (rsurface.ent_flags & RENDER_ADDITIVE)
7368                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7369         else if (t->currentalpha < 1)
7370                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7371         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7372                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7373         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7374                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7375         if (t->backgroundnumskinframes)
7376                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7377         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7378         {
7379                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7380                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7381         }
7382         else
7383                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7384         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7385                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7386
7387         // there is no tcmod
7388         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7389         {
7390                 t->currenttexmatrix = r_waterscrollmatrix;
7391                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7392         }
7393         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7394         {
7395                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7396                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7397         }
7398
7399         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7400                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7401         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7402                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7403
7404         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7405         if (t->currentskinframe->qpixels)
7406                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7407         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7408         if (!t->basetexture)
7409                 t->basetexture = r_texture_notexture;
7410         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7411         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7412         t->nmaptexture = t->currentskinframe->nmap;
7413         if (!t->nmaptexture)
7414                 t->nmaptexture = r_texture_blanknormalmap;
7415         t->glosstexture = r_texture_black;
7416         t->glowtexture = t->currentskinframe->glow;
7417         t->fogtexture = t->currentskinframe->fog;
7418         t->reflectmasktexture = t->currentskinframe->reflect;
7419         if (t->backgroundnumskinframes)
7420         {
7421                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7422                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7423                 t->backgroundglosstexture = r_texture_black;
7424                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7425                 if (!t->backgroundnmaptexture)
7426                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7427         }
7428         else
7429         {
7430                 t->backgroundbasetexture = r_texture_white;
7431                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7432                 t->backgroundglosstexture = r_texture_black;
7433                 t->backgroundglowtexture = NULL;
7434         }
7435         t->specularpower = r_shadow_glossexponent.value;
7436         // TODO: store reference values for these in the texture?
7437         t->specularscale = 0;
7438         if (r_shadow_gloss.integer > 0)
7439         {
7440                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7441                 {
7442                         if (r_shadow_glossintensity.value > 0)
7443                         {
7444                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7445                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7446                                 t->specularscale = r_shadow_glossintensity.value;
7447                         }
7448                 }
7449                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7450                 {
7451                         t->glosstexture = r_texture_white;
7452                         t->backgroundglosstexture = r_texture_white;
7453                         t->specularscale = r_shadow_gloss2intensity.value;
7454                         t->specularpower = r_shadow_gloss2exponent.value;
7455                 }
7456         }
7457         t->specularscale *= t->specularscalemod;
7458         t->specularpower *= t->specularpowermod;
7459
7460         // lightmaps mode looks bad with dlights using actual texturing, so turn
7461         // off the colormap and glossmap, but leave the normalmap on as it still
7462         // accurately represents the shading involved
7463         if (gl_lightmaps.integer)
7464         {
7465                 t->basetexture = r_texture_grey128;
7466                 t->pantstexture = r_texture_black;
7467                 t->shirttexture = r_texture_black;
7468                 t->nmaptexture = r_texture_blanknormalmap;
7469                 t->glosstexture = r_texture_black;
7470                 t->glowtexture = NULL;
7471                 t->fogtexture = NULL;
7472                 t->reflectmasktexture = NULL;
7473                 t->backgroundbasetexture = NULL;
7474                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7475                 t->backgroundglosstexture = r_texture_black;
7476                 t->backgroundglowtexture = NULL;
7477                 t->specularscale = 0;
7478                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7479         }
7480
7481         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7482         VectorClear(t->dlightcolor);
7483         t->currentnumlayers = 0;
7484         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7485         {
7486                 int blendfunc1, blendfunc2;
7487                 qboolean depthmask;
7488                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7489                 {
7490                         blendfunc1 = GL_SRC_ALPHA;
7491                         blendfunc2 = GL_ONE;
7492                 }
7493                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7494                 {
7495                         blendfunc1 = GL_SRC_ALPHA;
7496                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7497                 }
7498                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7499                 {
7500                         blendfunc1 = t->customblendfunc[0];
7501                         blendfunc2 = t->customblendfunc[1];
7502                 }
7503                 else
7504                 {
7505                         blendfunc1 = GL_ONE;
7506                         blendfunc2 = GL_ZERO;
7507                 }
7508                 // don't colormod evilblend textures
7509                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7510                         VectorSet(t->lightmapcolor, 1, 1, 1);
7511                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7512                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7513                 {
7514                         // fullbright is not affected by r_refdef.lightmapintensity
7515                         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]);
7516                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7517                                 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]);
7518                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7519                                 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]);
7520                 }
7521                 else
7522                 {
7523                         vec3_t ambientcolor;
7524                         float colorscale;
7525                         // set the color tint used for lights affecting this surface
7526                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7527                         colorscale = 2;
7528                         // q3bsp has no lightmap updates, so the lightstylevalue that
7529                         // would normally be baked into the lightmap must be
7530                         // applied to the color
7531                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7532                         if (model->type == mod_brushq3)
7533                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7534                         colorscale *= r_refdef.lightmapintensity;
7535                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7536                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7537                         // basic lit geometry
7538                         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]);
7539                         // add pants/shirt if needed
7540                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7541                                 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]);
7542                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7543                                 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]);
7544                         // now add ambient passes if needed
7545                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7546                         {
7547                                 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]);
7548                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7549                                         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]);
7550                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7551                                         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]);
7552                         }
7553                 }
7554                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7555                         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]);
7556                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7557                 {
7558                         // if this is opaque use alpha blend which will darken the earlier
7559                         // passes cheaply.
7560                         //
7561                         // if this is an alpha blended material, all the earlier passes
7562                         // were darkened by fog already, so we only need to add the fog
7563                         // color ontop through the fog mask texture
7564                         //
7565                         // if this is an additive blended material, all the earlier passes
7566                         // were darkened by fog already, and we should not add fog color
7567                         // (because the background was not darkened, there is no fog color
7568                         // that was lost behind it).
7569                         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]);
7570                 }
7571         }
7572
7573         return t->currentframe;
7574 }
7575
7576 rsurfacestate_t rsurface;
7577
7578 void RSurf_ActiveWorldEntity(void)
7579 {
7580         dp_model_t *model = r_refdef.scene.worldmodel;
7581         //if (rsurface.entity == r_refdef.scene.worldentity)
7582         //      return;
7583         rsurface.entity = r_refdef.scene.worldentity;
7584         rsurface.skeleton = NULL;
7585         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7586         rsurface.ent_skinnum = 0;
7587         rsurface.ent_qwskin = -1;
7588         rsurface.ent_shadertime = 0;
7589         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7590         rsurface.matrix = identitymatrix;
7591         rsurface.inversematrix = identitymatrix;
7592         rsurface.matrixscale = 1;
7593         rsurface.inversematrixscale = 1;
7594         R_EntityMatrix(&identitymatrix);
7595         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7596         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7597         rsurface.fograngerecip = r_refdef.fograngerecip;
7598         rsurface.fogheightfade = r_refdef.fogheightfade;
7599         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7600         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7601         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7602         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7603         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7604         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7605         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7606         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7607         rsurface.colormod[3] = 1;
7608         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);
7609         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7610         rsurface.frameblend[0].lerp = 1;
7611         rsurface.ent_alttextures = false;
7612         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7613         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7614         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7615         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7616         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7617         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7618         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7619         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7620         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7621         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7622         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7623         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7624         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7625         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7626         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7627         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7628         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7629         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7630         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7631         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7632         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7633         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7634         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7635         rsurface.modelelement3i = model->surfmesh.data_element3i;
7636         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7637         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7638         rsurface.modelelement3s = model->surfmesh.data_element3s;
7639         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7640         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7641         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7642         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7643         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7644         rsurface.modelsurfaces = model->data_surfaces;
7645         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7646         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7647         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7648         rsurface.modelgeneratedvertex = false;
7649         rsurface.batchgeneratedvertex = false;
7650         rsurface.batchfirstvertex = 0;
7651         rsurface.batchnumvertices = 0;
7652         rsurface.batchfirsttriangle = 0;
7653         rsurface.batchnumtriangles = 0;
7654         rsurface.batchvertex3f  = NULL;
7655         rsurface.batchvertex3f_vertexbuffer = NULL;
7656         rsurface.batchvertex3f_bufferoffset = 0;
7657         rsurface.batchsvector3f = NULL;
7658         rsurface.batchsvector3f_vertexbuffer = NULL;
7659         rsurface.batchsvector3f_bufferoffset = 0;
7660         rsurface.batchtvector3f = NULL;
7661         rsurface.batchtvector3f_vertexbuffer = NULL;
7662         rsurface.batchtvector3f_bufferoffset = 0;
7663         rsurface.batchnormal3f  = NULL;
7664         rsurface.batchnormal3f_vertexbuffer = NULL;
7665         rsurface.batchnormal3f_bufferoffset = 0;
7666         rsurface.batchlightmapcolor4f = NULL;
7667         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7668         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7669         rsurface.batchtexcoordtexture2f = NULL;
7670         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7671         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7672         rsurface.batchtexcoordlightmap2f = NULL;
7673         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7674         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7675         rsurface.batchvertexmesh = NULL;
7676         rsurface.batchvertexmeshbuffer = NULL;
7677         rsurface.batchvertex3fbuffer = NULL;
7678         rsurface.batchelement3i = NULL;
7679         rsurface.batchelement3i_indexbuffer = NULL;
7680         rsurface.batchelement3i_bufferoffset = 0;
7681         rsurface.batchelement3s = NULL;
7682         rsurface.batchelement3s_indexbuffer = NULL;
7683         rsurface.batchelement3s_bufferoffset = 0;
7684         rsurface.passcolor4f = NULL;
7685         rsurface.passcolor4f_vertexbuffer = NULL;
7686         rsurface.passcolor4f_bufferoffset = 0;
7687 }
7688
7689 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7690 {
7691         dp_model_t *model = ent->model;
7692         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7693         //      return;
7694         rsurface.entity = (entity_render_t *)ent;
7695         rsurface.skeleton = ent->skeleton;
7696         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7697         rsurface.ent_skinnum = ent->skinnum;
7698         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;
7699         rsurface.ent_shadertime = ent->shadertime;
7700         rsurface.ent_flags = ent->flags;
7701         rsurface.matrix = ent->matrix;
7702         rsurface.inversematrix = ent->inversematrix;
7703         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7704         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7705         R_EntityMatrix(&rsurface.matrix);
7706         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7707         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7708         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7709         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7710         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7711         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7712         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7713         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7714         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7715         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7716         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7717         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7718         rsurface.colormod[3] = ent->alpha;
7719         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7720         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7721         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7722         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7723         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7724         if (ent->model->brush.submodel && !prepass)
7725         {
7726                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7727                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7728         }
7729         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7730         {
7731                 if (ent->animcache_vertex3f)
7732                 {
7733                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7734                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7735                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7736                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7737                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7738                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7739                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7740                 }
7741                 else if (wanttangents)
7742                 {
7743                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7744                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7745                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7746                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7747                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7748                         rsurface.modelvertexmesh = NULL;
7749                         rsurface.modelvertexmeshbuffer = NULL;
7750                         rsurface.modelvertex3fbuffer = NULL;
7751                 }
7752                 else if (wantnormals)
7753                 {
7754                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7755                         rsurface.modelsvector3f = NULL;
7756                         rsurface.modeltvector3f = NULL;
7757                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7758                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7759                         rsurface.modelvertexmesh = NULL;
7760                         rsurface.modelvertexmeshbuffer = NULL;
7761                         rsurface.modelvertex3fbuffer = NULL;
7762                 }
7763                 else
7764                 {
7765                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7766                         rsurface.modelsvector3f = NULL;
7767                         rsurface.modeltvector3f = NULL;
7768                         rsurface.modelnormal3f = NULL;
7769                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7770                         rsurface.modelvertexmesh = NULL;
7771                         rsurface.modelvertexmeshbuffer = NULL;
7772                         rsurface.modelvertex3fbuffer = NULL;
7773                 }
7774                 rsurface.modelvertex3f_vertexbuffer = 0;
7775                 rsurface.modelvertex3f_bufferoffset = 0;
7776                 rsurface.modelsvector3f_vertexbuffer = 0;
7777                 rsurface.modelsvector3f_bufferoffset = 0;
7778                 rsurface.modeltvector3f_vertexbuffer = 0;
7779                 rsurface.modeltvector3f_bufferoffset = 0;
7780                 rsurface.modelnormal3f_vertexbuffer = 0;
7781                 rsurface.modelnormal3f_bufferoffset = 0;
7782                 rsurface.modelgeneratedvertex = true;
7783         }
7784         else
7785         {
7786                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7787                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7788                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7789                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7790                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7791                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7792                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7793                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7794                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7795                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7796                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7797                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7798                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7799                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7800                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7801                 rsurface.modelgeneratedvertex = false;
7802         }
7803         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7804         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7805         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7806         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7807         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7808         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7809         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7810         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7811         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7812         rsurface.modelelement3i = model->surfmesh.data_element3i;
7813         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7814         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7815         rsurface.modelelement3s = model->surfmesh.data_element3s;
7816         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7817         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7818         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7819         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7820         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7821         rsurface.modelsurfaces = model->data_surfaces;
7822         rsurface.batchgeneratedvertex = false;
7823         rsurface.batchfirstvertex = 0;
7824         rsurface.batchnumvertices = 0;
7825         rsurface.batchfirsttriangle = 0;
7826         rsurface.batchnumtriangles = 0;
7827         rsurface.batchvertex3f  = NULL;
7828         rsurface.batchvertex3f_vertexbuffer = NULL;
7829         rsurface.batchvertex3f_bufferoffset = 0;
7830         rsurface.batchsvector3f = NULL;
7831         rsurface.batchsvector3f_vertexbuffer = NULL;
7832         rsurface.batchsvector3f_bufferoffset = 0;
7833         rsurface.batchtvector3f = NULL;
7834         rsurface.batchtvector3f_vertexbuffer = NULL;
7835         rsurface.batchtvector3f_bufferoffset = 0;
7836         rsurface.batchnormal3f  = NULL;
7837         rsurface.batchnormal3f_vertexbuffer = NULL;
7838         rsurface.batchnormal3f_bufferoffset = 0;
7839         rsurface.batchlightmapcolor4f = NULL;
7840         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7841         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7842         rsurface.batchtexcoordtexture2f = NULL;
7843         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7844         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7845         rsurface.batchtexcoordlightmap2f = NULL;
7846         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7847         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7848         rsurface.batchvertexmesh = NULL;
7849         rsurface.batchvertexmeshbuffer = NULL;
7850         rsurface.batchvertex3fbuffer = NULL;
7851         rsurface.batchelement3i = NULL;
7852         rsurface.batchelement3i_indexbuffer = NULL;
7853         rsurface.batchelement3i_bufferoffset = 0;
7854         rsurface.batchelement3s = NULL;
7855         rsurface.batchelement3s_indexbuffer = NULL;
7856         rsurface.batchelement3s_bufferoffset = 0;
7857         rsurface.passcolor4f = NULL;
7858         rsurface.passcolor4f_vertexbuffer = NULL;
7859         rsurface.passcolor4f_bufferoffset = 0;
7860 }
7861
7862 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)
7863 {
7864         rsurface.entity = r_refdef.scene.worldentity;
7865         rsurface.skeleton = NULL;
7866         rsurface.ent_skinnum = 0;
7867         rsurface.ent_qwskin = -1;
7868         rsurface.ent_shadertime = shadertime;
7869         rsurface.ent_flags = entflags;
7870         rsurface.modelnumvertices = numvertices;
7871         rsurface.modelnumtriangles = numtriangles;
7872         rsurface.matrix = *matrix;
7873         rsurface.inversematrix = *inversematrix;
7874         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7875         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7876         R_EntityMatrix(&rsurface.matrix);
7877         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7878         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7879         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7880         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7881         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7882         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7883         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7884         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7885         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7886         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7887         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7888         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7889         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);
7890         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7891         rsurface.frameblend[0].lerp = 1;
7892         rsurface.ent_alttextures = false;
7893         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7894         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7895         if (wanttangents)
7896         {
7897                 rsurface.modelvertex3f = (float *)vertex3f;
7898                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7899                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7900                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7901         }
7902         else if (wantnormals)
7903         {
7904                 rsurface.modelvertex3f = (float *)vertex3f;
7905                 rsurface.modelsvector3f = NULL;
7906                 rsurface.modeltvector3f = NULL;
7907                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7908         }
7909         else
7910         {
7911                 rsurface.modelvertex3f = (float *)vertex3f;
7912                 rsurface.modelsvector3f = NULL;
7913                 rsurface.modeltvector3f = NULL;
7914                 rsurface.modelnormal3f = NULL;
7915         }
7916         rsurface.modelvertexmesh = NULL;
7917         rsurface.modelvertexmeshbuffer = NULL;
7918         rsurface.modelvertex3fbuffer = NULL;
7919         rsurface.modelvertex3f_vertexbuffer = 0;
7920         rsurface.modelvertex3f_bufferoffset = 0;
7921         rsurface.modelsvector3f_vertexbuffer = 0;
7922         rsurface.modelsvector3f_bufferoffset = 0;
7923         rsurface.modeltvector3f_vertexbuffer = 0;
7924         rsurface.modeltvector3f_bufferoffset = 0;
7925         rsurface.modelnormal3f_vertexbuffer = 0;
7926         rsurface.modelnormal3f_bufferoffset = 0;
7927         rsurface.modelgeneratedvertex = true;
7928         rsurface.modellightmapcolor4f  = (float *)color4f;
7929         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7930         rsurface.modellightmapcolor4f_bufferoffset = 0;
7931         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7932         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7933         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7934         rsurface.modeltexcoordlightmap2f  = NULL;
7935         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7936         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7937         rsurface.modelelement3i = (int *)element3i;
7938         rsurface.modelelement3i_indexbuffer = NULL;
7939         rsurface.modelelement3i_bufferoffset = 0;
7940         rsurface.modelelement3s = (unsigned short *)element3s;
7941         rsurface.modelelement3s_indexbuffer = NULL;
7942         rsurface.modelelement3s_bufferoffset = 0;
7943         rsurface.modellightmapoffsets = NULL;
7944         rsurface.modelsurfaces = NULL;
7945         rsurface.batchgeneratedvertex = false;
7946         rsurface.batchfirstvertex = 0;
7947         rsurface.batchnumvertices = 0;
7948         rsurface.batchfirsttriangle = 0;
7949         rsurface.batchnumtriangles = 0;
7950         rsurface.batchvertex3f  = NULL;
7951         rsurface.batchvertex3f_vertexbuffer = NULL;
7952         rsurface.batchvertex3f_bufferoffset = 0;
7953         rsurface.batchsvector3f = NULL;
7954         rsurface.batchsvector3f_vertexbuffer = NULL;
7955         rsurface.batchsvector3f_bufferoffset = 0;
7956         rsurface.batchtvector3f = NULL;
7957         rsurface.batchtvector3f_vertexbuffer = NULL;
7958         rsurface.batchtvector3f_bufferoffset = 0;
7959         rsurface.batchnormal3f  = NULL;
7960         rsurface.batchnormal3f_vertexbuffer = NULL;
7961         rsurface.batchnormal3f_bufferoffset = 0;
7962         rsurface.batchlightmapcolor4f = NULL;
7963         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7964         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7965         rsurface.batchtexcoordtexture2f = NULL;
7966         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7967         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7968         rsurface.batchtexcoordlightmap2f = NULL;
7969         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7970         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7971         rsurface.batchvertexmesh = NULL;
7972         rsurface.batchvertexmeshbuffer = NULL;
7973         rsurface.batchvertex3fbuffer = NULL;
7974         rsurface.batchelement3i = NULL;
7975         rsurface.batchelement3i_indexbuffer = NULL;
7976         rsurface.batchelement3i_bufferoffset = 0;
7977         rsurface.batchelement3s = NULL;
7978         rsurface.batchelement3s_indexbuffer = NULL;
7979         rsurface.batchelement3s_bufferoffset = 0;
7980         rsurface.passcolor4f = NULL;
7981         rsurface.passcolor4f_vertexbuffer = NULL;
7982         rsurface.passcolor4f_bufferoffset = 0;
7983
7984         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7985         {
7986                 if ((wantnormals || wanttangents) && !normal3f)
7987                 {
7988                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7989                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7990                 }
7991                 if (wanttangents && !svector3f)
7992                 {
7993                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7994                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7995                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7996                 }
7997         }
7998 }
7999
8000 float RSurf_FogPoint(const float *v)
8001 {
8002         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8003         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8004         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8005         float FogHeightFade = r_refdef.fogheightfade;
8006         float fogfrac;
8007         unsigned int fogmasktableindex;
8008         if (r_refdef.fogplaneviewabove)
8009                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8010         else
8011                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8012         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8013         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8014 }
8015
8016 float RSurf_FogVertex(const float *v)
8017 {
8018         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8019         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8020         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8021         float FogHeightFade = rsurface.fogheightfade;
8022         float fogfrac;
8023         unsigned int fogmasktableindex;
8024         if (r_refdef.fogplaneviewabove)
8025                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8026         else
8027                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8028         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8029         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8030 }
8031
8032 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8033 {
8034         int i;
8035         for (i = 0;i < numelements;i++)
8036                 outelement3i[i] = inelement3i[i] + adjust;
8037 }
8038
8039 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8040 extern cvar_t gl_vbo;
8041 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8042 {
8043         int deformindex;
8044         int firsttriangle;
8045         int numtriangles;
8046         int firstvertex;
8047         int endvertex;
8048         int numvertices;
8049         int surfacefirsttriangle;
8050         int surfacenumtriangles;
8051         int surfacefirstvertex;
8052         int surfaceendvertex;
8053         int surfacenumvertices;
8054         int batchnumvertices;
8055         int batchnumtriangles;
8056         int needsupdate;
8057         int i, j;
8058         qboolean gaps;
8059         qboolean dynamicvertex;
8060         float amplitude;
8061         float animpos;
8062         float scale;
8063         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8064         float waveparms[4];
8065         q3shaderinfo_deform_t *deform;
8066         const msurface_t *surface, *firstsurface;
8067         r_vertexmesh_t *vertexmesh;
8068         if (!texturenumsurfaces)
8069                 return;
8070         // find vertex range of this surface batch
8071         gaps = false;
8072         firstsurface = texturesurfacelist[0];
8073         firsttriangle = firstsurface->num_firsttriangle;
8074         batchnumvertices = 0;
8075         batchnumtriangles = 0;
8076         firstvertex = endvertex = firstsurface->num_firstvertex;
8077         for (i = 0;i < texturenumsurfaces;i++)
8078         {
8079                 surface = texturesurfacelist[i];
8080                 if (surface != firstsurface + i)
8081                         gaps = true;
8082                 surfacefirstvertex = surface->num_firstvertex;
8083                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8084                 surfacenumvertices = surface->num_vertices;
8085                 surfacenumtriangles = surface->num_triangles;
8086                 if (firstvertex > surfacefirstvertex)
8087                         firstvertex = surfacefirstvertex;
8088                 if (endvertex < surfaceendvertex)
8089                         endvertex = surfaceendvertex;
8090                 batchnumvertices += surfacenumvertices;
8091                 batchnumtriangles += surfacenumtriangles;
8092         }
8093
8094         // we now know the vertex range used, and if there are any gaps in it
8095         rsurface.batchfirstvertex = firstvertex;
8096         rsurface.batchnumvertices = endvertex - firstvertex;
8097         rsurface.batchfirsttriangle = firsttriangle;
8098         rsurface.batchnumtriangles = batchnumtriangles;
8099
8100         // this variable holds flags for which properties have been updated that
8101         // may require regenerating vertexmesh array...
8102         needsupdate = 0;
8103
8104         // check if any dynamic vertex processing must occur
8105         dynamicvertex = false;
8106
8107         // if there is a chance of animated vertex colors, it's a dynamic batch
8108         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8109         {
8110                 dynamicvertex = true;
8111                 batchneed |= BATCHNEED_NOGAPS;
8112                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8113         }
8114
8115         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8116         {
8117                 switch (deform->deform)
8118                 {
8119                 default:
8120                 case Q3DEFORM_PROJECTIONSHADOW:
8121                 case Q3DEFORM_TEXT0:
8122                 case Q3DEFORM_TEXT1:
8123                 case Q3DEFORM_TEXT2:
8124                 case Q3DEFORM_TEXT3:
8125                 case Q3DEFORM_TEXT4:
8126                 case Q3DEFORM_TEXT5:
8127                 case Q3DEFORM_TEXT6:
8128                 case Q3DEFORM_TEXT7:
8129                 case Q3DEFORM_NONE:
8130                         break;
8131                 case Q3DEFORM_AUTOSPRITE:
8132                         dynamicvertex = true;
8133                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8134                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8135                         break;
8136                 case Q3DEFORM_AUTOSPRITE2:
8137                         dynamicvertex = true;
8138                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8139                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8140                         break;
8141                 case Q3DEFORM_NORMAL:
8142                         dynamicvertex = true;
8143                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8144                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8145                         break;
8146                 case Q3DEFORM_WAVE:
8147                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8148                                 break; // if wavefunc is a nop, ignore this transform
8149                         dynamicvertex = true;
8150                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8151                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8152                         break;
8153                 case Q3DEFORM_BULGE:
8154                         dynamicvertex = true;
8155                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8156                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8157                         break;
8158                 case Q3DEFORM_MOVE:
8159                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8160                                 break; // if wavefunc is a nop, ignore this transform
8161                         dynamicvertex = true;
8162                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8163                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8164                         break;
8165                 }
8166         }
8167         switch(rsurface.texture->tcgen.tcgen)
8168         {
8169         default:
8170         case Q3TCGEN_TEXTURE:
8171                 break;
8172         case Q3TCGEN_LIGHTMAP:
8173                 dynamicvertex = true;
8174                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8175                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8176                 break;
8177         case Q3TCGEN_VECTOR:
8178                 dynamicvertex = true;
8179                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8180                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8181                 break;
8182         case Q3TCGEN_ENVIRONMENT:
8183                 dynamicvertex = true;
8184                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8185                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8186                 break;
8187         }
8188         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8189         {
8190                 dynamicvertex = true;
8191                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8192                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8193         }
8194
8195         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8196         {
8197                 dynamicvertex = true;
8198                 batchneed |= BATCHNEED_NOGAPS;
8199                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8200         }
8201
8202         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8203         {
8204                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8205                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8206                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8207                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8208                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8209                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8210                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8211         }
8212
8213         // when the model data has no vertex buffer (dynamic mesh), we need to
8214         // eliminate gaps
8215         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8216                 batchneed |= BATCHNEED_NOGAPS;
8217
8218         // if needsupdate, we have to do a dynamic vertex batch for sure
8219         if (needsupdate & batchneed)
8220                 dynamicvertex = true;
8221
8222         // see if we need to build vertexmesh from arrays
8223         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8224                 dynamicvertex = true;
8225
8226         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8227         // also some drivers strongly dislike firstvertex
8228         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8229                 dynamicvertex = true;
8230
8231         rsurface.batchvertex3f = rsurface.modelvertex3f;
8232         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8233         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8234         rsurface.batchsvector3f = rsurface.modelsvector3f;
8235         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8236         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8237         rsurface.batchtvector3f = rsurface.modeltvector3f;
8238         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8239         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8240         rsurface.batchnormal3f = rsurface.modelnormal3f;
8241         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8242         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8243         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8244         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8245         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8246         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8247         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8248         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8249         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8250         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8251         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8252         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8253         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8254         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8255         rsurface.batchelement3i = rsurface.modelelement3i;
8256         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8257         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8258         rsurface.batchelement3s = rsurface.modelelement3s;
8259         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8260         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8261
8262         // if any dynamic vertex processing has to occur in software, we copy the
8263         // entire surface list together before processing to rebase the vertices
8264         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8265         //
8266         // if any gaps exist and we do not have a static vertex buffer, we have to
8267         // copy the surface list together to avoid wasting upload bandwidth on the
8268         // vertices in the gaps.
8269         //
8270         // if gaps exist and we have a static vertex buffer, we still have to
8271         // combine the index buffer ranges into one dynamic index buffer.
8272         //
8273         // in all cases we end up with data that can be drawn in one call.
8274
8275         if (!dynamicvertex)
8276         {
8277                 // static vertex data, just set pointers...
8278                 rsurface.batchgeneratedvertex = false;
8279                 // if there are gaps, we want to build a combined index buffer,
8280                 // otherwise use the original static buffer with an appropriate offset
8281                 if (gaps)
8282                 {
8283                         // build a new triangle elements array for this batch
8284                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8285                         rsurface.batchfirsttriangle = 0;
8286                         numtriangles = 0;
8287                         for (i = 0;i < texturenumsurfaces;i++)
8288                         {
8289                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8290                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8291                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8292                                 numtriangles += surfacenumtriangles;
8293                         }
8294                         rsurface.batchelement3i_indexbuffer = NULL;
8295                         rsurface.batchelement3i_bufferoffset = 0;
8296                         rsurface.batchelement3s = NULL;
8297                         rsurface.batchelement3s_indexbuffer = NULL;
8298                         rsurface.batchelement3s_bufferoffset = 0;
8299                         if (endvertex <= 65536)
8300                         {
8301                                 // make a 16bit (unsigned short) index array if possible
8302                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8303                                 for (i = 0;i < numtriangles*3;i++)
8304                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8305                         }
8306                 }
8307                 return;
8308         }
8309
8310         // something needs software processing, do it for real...
8311         // we only directly handle separate array data in this case and then
8312         // generate interleaved data if needed...
8313         rsurface.batchgeneratedvertex = true;
8314
8315         // now copy the vertex data into a combined array and make an index array
8316         // (this is what Quake3 does all the time)
8317         //if (gaps || rsurface.batchfirstvertex)
8318         {
8319                 rsurface.batchvertex3fbuffer = NULL;
8320                 rsurface.batchvertexmesh = NULL;
8321                 rsurface.batchvertexmeshbuffer = NULL;
8322                 rsurface.batchvertex3f = NULL;
8323                 rsurface.batchvertex3f_vertexbuffer = NULL;
8324                 rsurface.batchvertex3f_bufferoffset = 0;
8325                 rsurface.batchsvector3f = NULL;
8326                 rsurface.batchsvector3f_vertexbuffer = NULL;
8327                 rsurface.batchsvector3f_bufferoffset = 0;
8328                 rsurface.batchtvector3f = NULL;
8329                 rsurface.batchtvector3f_vertexbuffer = NULL;
8330                 rsurface.batchtvector3f_bufferoffset = 0;
8331                 rsurface.batchnormal3f = NULL;
8332                 rsurface.batchnormal3f_vertexbuffer = NULL;
8333                 rsurface.batchnormal3f_bufferoffset = 0;
8334                 rsurface.batchlightmapcolor4f = NULL;
8335                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8336                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8337                 rsurface.batchtexcoordtexture2f = NULL;
8338                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8339                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8340                 rsurface.batchtexcoordlightmap2f = NULL;
8341                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8342                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8343                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8344                 rsurface.batchelement3i_indexbuffer = NULL;
8345                 rsurface.batchelement3i_bufferoffset = 0;
8346                 rsurface.batchelement3s = NULL;
8347                 rsurface.batchelement3s_indexbuffer = NULL;
8348                 rsurface.batchelement3s_bufferoffset = 0;
8349                 // we'll only be setting up certain arrays as needed
8350                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8351                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8352                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8353                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8354                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8355                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8356                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8357                 {
8358                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8359                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8360                 }
8361                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8362                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8363                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8364                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8365                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8366                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8367                 numvertices = 0;
8368                 numtriangles = 0;
8369                 for (i = 0;i < texturenumsurfaces;i++)
8370                 {
8371                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8372                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8373                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8374                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8375                         // copy only the data requested
8376                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8377                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8378                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8379                         {
8380                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8381                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8382                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8383                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8384                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8385                                 {
8386                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8387                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8388                                 }
8389                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8390                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8391                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8392                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8393                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8394                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8395                         }
8396                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8397                         numvertices += surfacenumvertices;
8398                         numtriangles += surfacenumtriangles;
8399                 }
8400
8401                 // generate a 16bit index array as well if possible
8402                 // (in general, dynamic batches fit)
8403                 if (numvertices <= 65536)
8404                 {
8405                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8406                         for (i = 0;i < numtriangles*3;i++)
8407                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8408                 }
8409
8410                 // since we've copied everything, the batch now starts at 0
8411                 rsurface.batchfirstvertex = 0;
8412                 rsurface.batchnumvertices = batchnumvertices;
8413                 rsurface.batchfirsttriangle = 0;
8414                 rsurface.batchnumtriangles = batchnumtriangles;
8415         }
8416
8417         // q1bsp surfaces rendered in vertex color mode have to have colors
8418         // calculated based on lightstyles
8419         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8420         {
8421                 // generate color arrays for the surfaces in this list
8422                 int c[4];
8423                 int scale;
8424                 int size3;
8425                 const int *offsets;
8426                 const unsigned char *lm;
8427                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8428                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8429                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8430                 numvertices = 0;
8431                 for (i = 0;i < texturenumsurfaces;i++)
8432                 {
8433                         surface = texturesurfacelist[i];
8434                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8435                         surfacenumvertices = surface->num_vertices;
8436                         if (surface->lightmapinfo->samples)
8437                         {
8438                                 for (j = 0;j < surfacenumvertices;j++)
8439                                 {
8440                                         lm = surface->lightmapinfo->samples + offsets[j];
8441                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8442                                         VectorScale(lm, scale, c);
8443                                         if (surface->lightmapinfo->styles[1] != 255)
8444                                         {
8445                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8446                                                 lm += size3;
8447                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8448                                                 VectorMA(c, scale, lm, c);
8449                                                 if (surface->lightmapinfo->styles[2] != 255)
8450                                                 {
8451                                                         lm += size3;
8452                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8453                                                         VectorMA(c, scale, lm, c);
8454                                                         if (surface->lightmapinfo->styles[3] != 255)
8455                                                         {
8456                                                                 lm += size3;
8457                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8458                                                                 VectorMA(c, scale, lm, c);
8459                                                         }
8460                                                 }
8461                                         }
8462                                         c[0] >>= 7;
8463                                         c[1] >>= 7;
8464                                         c[2] >>= 7;
8465                                         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);
8466                                         numvertices++;
8467                                 }
8468                         }
8469                         else
8470                         {
8471                                 for (j = 0;j < surfacenumvertices;j++)
8472                                 {
8473                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8474                                         numvertices++;
8475                                 }
8476                         }
8477                 }
8478         }
8479
8480         // if vertices are deformed (sprite flares and things in maps, possibly
8481         // water waves, bulges and other deformations), modify the copied vertices
8482         // in place
8483         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8484         {
8485                 switch (deform->deform)
8486                 {
8487                 default:
8488                 case Q3DEFORM_PROJECTIONSHADOW:
8489                 case Q3DEFORM_TEXT0:
8490                 case Q3DEFORM_TEXT1:
8491                 case Q3DEFORM_TEXT2:
8492                 case Q3DEFORM_TEXT3:
8493                 case Q3DEFORM_TEXT4:
8494                 case Q3DEFORM_TEXT5:
8495                 case Q3DEFORM_TEXT6:
8496                 case Q3DEFORM_TEXT7:
8497                 case Q3DEFORM_NONE:
8498                         break;
8499                 case Q3DEFORM_AUTOSPRITE:
8500                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8501                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8502                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8503                         VectorNormalize(newforward);
8504                         VectorNormalize(newright);
8505                         VectorNormalize(newup);
8506 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8507 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8508 //                      rsurface.batchvertex3f_bufferoffset = 0;
8509 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8510 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8511 //                      rsurface.batchsvector3f_bufferoffset = 0;
8512 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8513 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8514 //                      rsurface.batchtvector3f_bufferoffset = 0;
8515 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8516 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8517 //                      rsurface.batchnormal3f_bufferoffset = 0;
8518                         // a single autosprite surface can contain multiple sprites...
8519                         for (j = 0;j < batchnumvertices - 3;j += 4)
8520                         {
8521                                 VectorClear(center);
8522                                 for (i = 0;i < 4;i++)
8523                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8524                                 VectorScale(center, 0.25f, center);
8525                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8526                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8527                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8528                                 for (i = 0;i < 4;i++)
8529                                 {
8530                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8531                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8532                                 }
8533                         }
8534                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8535                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8536                         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);
8537                         break;
8538                 case Q3DEFORM_AUTOSPRITE2:
8539                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8540                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8541                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8542                         VectorNormalize(newforward);
8543                         VectorNormalize(newright);
8544                         VectorNormalize(newup);
8545 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8546 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8547 //                      rsurface.batchvertex3f_bufferoffset = 0;
8548                         {
8549                                 const float *v1, *v2;
8550                                 vec3_t start, end;
8551                                 float f, l;
8552                                 struct
8553                                 {
8554                                         float length2;
8555                                         const float *v1;
8556                                         const float *v2;
8557                                 }
8558                                 shortest[2];
8559                                 memset(shortest, 0, sizeof(shortest));
8560                                 // a single autosprite surface can contain multiple sprites...
8561                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8562                                 {
8563                                         VectorClear(center);
8564                                         for (i = 0;i < 4;i++)
8565                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8566                                         VectorScale(center, 0.25f, center);
8567                                         // find the two shortest edges, then use them to define the
8568                                         // axis vectors for rotating around the central axis
8569                                         for (i = 0;i < 6;i++)
8570                                         {
8571                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8572                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8573                                                 l = VectorDistance2(v1, v2);
8574                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8575                                                 if (v1[2] != v2[2])
8576                                                         l += (1.0f / 1024.0f);
8577                                                 if (shortest[0].length2 > l || i == 0)
8578                                                 {
8579                                                         shortest[1] = shortest[0];
8580                                                         shortest[0].length2 = l;
8581                                                         shortest[0].v1 = v1;
8582                                                         shortest[0].v2 = v2;
8583                                                 }
8584                                                 else if (shortest[1].length2 > l || i == 1)
8585                                                 {
8586                                                         shortest[1].length2 = l;
8587                                                         shortest[1].v1 = v1;
8588                                                         shortest[1].v2 = v2;
8589                                                 }
8590                                         }
8591                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8592                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8593                                         // this calculates the right vector from the shortest edge
8594                                         // and the up vector from the edge midpoints
8595                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8596                                         VectorNormalize(right);
8597                                         VectorSubtract(end, start, up);
8598                                         VectorNormalize(up);
8599                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8600                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8601                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8602                                         VectorNegate(forward, forward);
8603                                         VectorReflect(forward, 0, up, forward);
8604                                         VectorNormalize(forward);
8605                                         CrossProduct(up, forward, newright);
8606                                         VectorNormalize(newright);
8607                                         // rotate the quad around the up axis vector, this is made
8608                                         // especially easy by the fact we know the quad is flat,
8609                                         // so we only have to subtract the center position and
8610                                         // measure distance along the right vector, and then
8611                                         // multiply that by the newright vector and add back the
8612                                         // center position
8613                                         // we also need to subtract the old position to undo the
8614                                         // displacement from the center, which we do with a
8615                                         // DotProduct, the subtraction/addition of center is also
8616                                         // optimized into DotProducts here
8617                                         l = DotProduct(right, center);
8618                                         for (i = 0;i < 4;i++)
8619                                         {
8620                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8621                                                 f = DotProduct(right, v1) - l;
8622                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8623                                         }
8624                                 }
8625                         }
8626                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8627                         {
8628 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8629 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8630 //                              rsurface.batchnormal3f_bufferoffset = 0;
8631                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8632                         }
8633                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8634                         {
8635 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8636 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8637 //                              rsurface.batchsvector3f_bufferoffset = 0;
8638 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8639 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8640 //                              rsurface.batchtvector3f_bufferoffset = 0;
8641                                 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);
8642                         }
8643                         break;
8644                 case Q3DEFORM_NORMAL:
8645                         // deform the normals to make reflections wavey
8646                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8647                         rsurface.batchnormal3f_vertexbuffer = NULL;
8648                         rsurface.batchnormal3f_bufferoffset = 0;
8649                         for (j = 0;j < batchnumvertices;j++)
8650                         {
8651                                 float vertex[3];
8652                                 float *normal = rsurface.batchnormal3f + 3*j;
8653                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8654                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8655                                 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]);
8656                                 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]);
8657                                 VectorNormalize(normal);
8658                         }
8659                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8660                         {
8661 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8662 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8663 //                              rsurface.batchsvector3f_bufferoffset = 0;
8664 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8665 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8666 //                              rsurface.batchtvector3f_bufferoffset = 0;
8667                                 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);
8668                         }
8669                         break;
8670                 case Q3DEFORM_WAVE:
8671                         // deform vertex array to make wavey water and flags and such
8672                         waveparms[0] = deform->waveparms[0];
8673                         waveparms[1] = deform->waveparms[1];
8674                         waveparms[2] = deform->waveparms[2];
8675                         waveparms[3] = deform->waveparms[3];
8676                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8677                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8678                         // this is how a divisor of vertex influence on deformation
8679                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8680                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8681 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8682 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8683 //                      rsurface.batchvertex3f_bufferoffset = 0;
8684 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8685 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8686 //                      rsurface.batchnormal3f_bufferoffset = 0;
8687                         for (j = 0;j < batchnumvertices;j++)
8688                         {
8689                                 // if the wavefunc depends on time, evaluate it per-vertex
8690                                 if (waveparms[3])
8691                                 {
8692                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8693                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8694                                 }
8695                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8696                         }
8697                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8698                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8699                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8700                         {
8701 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8702 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8703 //                              rsurface.batchsvector3f_bufferoffset = 0;
8704 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8705 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8706 //                              rsurface.batchtvector3f_bufferoffset = 0;
8707                                 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);
8708                         }
8709                         break;
8710                 case Q3DEFORM_BULGE:
8711                         // deform vertex array to make the surface have moving bulges
8712 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8713 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8714 //                      rsurface.batchvertex3f_bufferoffset = 0;
8715 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8716 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8717 //                      rsurface.batchnormal3f_bufferoffset = 0;
8718                         for (j = 0;j < batchnumvertices;j++)
8719                         {
8720                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8721                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8722                         }
8723                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8724                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8725                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8726                         {
8727 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8728 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8729 //                              rsurface.batchsvector3f_bufferoffset = 0;
8730 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8731 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8732 //                              rsurface.batchtvector3f_bufferoffset = 0;
8733                                 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);
8734                         }
8735                         break;
8736                 case Q3DEFORM_MOVE:
8737                         // deform vertex array
8738                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8739                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8740                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8741                         VectorScale(deform->parms, scale, waveparms);
8742 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8743 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8744 //                      rsurface.batchvertex3f_bufferoffset = 0;
8745                         for (j = 0;j < batchnumvertices;j++)
8746                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8747                         break;
8748                 }
8749         }
8750
8751         // generate texcoords based on the chosen texcoord source
8752         switch(rsurface.texture->tcgen.tcgen)
8753         {
8754         default:
8755         case Q3TCGEN_TEXTURE:
8756                 break;
8757         case Q3TCGEN_LIGHTMAP:
8758 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8759 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8760 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8761                 if (rsurface.batchtexcoordlightmap2f)
8762                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8763                 break;
8764         case Q3TCGEN_VECTOR:
8765 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8766 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8767 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8768                 for (j = 0;j < batchnumvertices;j++)
8769                 {
8770                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8771                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8772                 }
8773                 break;
8774         case Q3TCGEN_ENVIRONMENT:
8775                 // make environment reflections using a spheremap
8776                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8777                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8778                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8779                 for (j = 0;j < batchnumvertices;j++)
8780                 {
8781                         // identical to Q3A's method, but executed in worldspace so
8782                         // carried models can be shiny too
8783
8784                         float viewer[3], d, reflected[3], worldreflected[3];
8785
8786                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8787                         // VectorNormalize(viewer);
8788
8789                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8790
8791                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8792                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8793                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8794                         // note: this is proportinal to viewer, so we can normalize later
8795
8796                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8797                         VectorNormalize(worldreflected);
8798
8799                         // note: this sphere map only uses world x and z!
8800                         // so positive and negative y will LOOK THE SAME.
8801                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8802                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8803                 }
8804                 break;
8805         }
8806         // the only tcmod that needs software vertex processing is turbulent, so
8807         // check for it here and apply the changes if needed
8808         // and we only support that as the first one
8809         // (handling a mixture of turbulent and other tcmods would be problematic
8810         //  without punting it entirely to a software path)
8811         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8812         {
8813                 amplitude = rsurface.texture->tcmods[0].parms[1];
8814                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8815 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8816 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8817 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8818                 for (j = 0;j < batchnumvertices;j++)
8819                 {
8820                         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);
8821                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8822                 }
8823         }
8824
8825         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8826         {
8827                 // convert the modified arrays to vertex structs
8828 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8829 //              rsurface.batchvertexmeshbuffer = NULL;
8830                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8831                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8832                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8833                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8834                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8835                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8836                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8837                 {
8838                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8839                         {
8840                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8841                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8842                         }
8843                 }
8844                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8845                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8846                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8847                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8848                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8849                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8850                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8851                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8852                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8853         }
8854 }
8855
8856 void RSurf_DrawBatch(void)
8857 {
8858         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8859         // through the pipeline, killing it earlier in the pipeline would have
8860         // per-surface overhead rather than per-batch overhead, so it's best to
8861         // reject it here, before it hits glDraw.
8862         if (rsurface.batchnumtriangles == 0)
8863                 return;
8864 #if 0
8865         // batch debugging code
8866         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8867         {
8868                 int i;
8869                 int j;
8870                 int c;
8871                 const int *e;
8872                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8873                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8874                 {
8875                         c = e[i];
8876                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8877                         {
8878                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8879                                 {
8880                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8881                                                 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);
8882                                         break;
8883                                 }
8884                         }
8885                 }
8886         }
8887 #endif
8888         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);
8889 }
8890
8891 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8892 {
8893         // pick the closest matching water plane
8894         int planeindex, vertexindex, bestplaneindex = -1;
8895         float d, bestd;
8896         vec3_t vert;
8897         const float *v;
8898         r_waterstate_waterplane_t *p;
8899         qboolean prepared = false;
8900         bestd = 0;
8901         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8902         {
8903                 if(p->camera_entity != rsurface.texture->camera_entity)
8904                         continue;
8905                 d = 0;
8906                 if(!prepared)
8907                 {
8908                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8909                         prepared = true;
8910                         if(rsurface.batchnumvertices == 0)
8911                                 break;
8912                 }
8913                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8914                 {
8915                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8916                         d += fabs(PlaneDiff(vert, &p->plane));
8917                 }
8918                 if (bestd > d || bestplaneindex < 0)
8919                 {
8920                         bestd = d;
8921                         bestplaneindex = planeindex;
8922                 }
8923         }
8924         return bestplaneindex;
8925         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8926         // this situation though, as it might be better to render single larger
8927         // batches with useless stuff (backface culled for example) than to
8928         // render multiple smaller batches
8929 }
8930
8931 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8932 {
8933         int i;
8934         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8935         rsurface.passcolor4f_vertexbuffer = 0;
8936         rsurface.passcolor4f_bufferoffset = 0;
8937         for (i = 0;i < rsurface.batchnumvertices;i++)
8938                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8939 }
8940
8941 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8942 {
8943         int i;
8944         float f;
8945         const float *v;
8946         const float *c;
8947         float *c2;
8948         if (rsurface.passcolor4f)
8949         {
8950                 // generate color arrays
8951                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8952                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8953                 rsurface.passcolor4f_vertexbuffer = 0;
8954                 rsurface.passcolor4f_bufferoffset = 0;
8955                 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)
8956                 {
8957                         f = RSurf_FogVertex(v);
8958                         c2[0] = c[0] * f;
8959                         c2[1] = c[1] * f;
8960                         c2[2] = c[2] * f;
8961                         c2[3] = c[3];
8962                 }
8963         }
8964         else
8965         {
8966                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8967                 rsurface.passcolor4f_vertexbuffer = 0;
8968                 rsurface.passcolor4f_bufferoffset = 0;
8969                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8970                 {
8971                         f = RSurf_FogVertex(v);
8972                         c2[0] = f;
8973                         c2[1] = f;
8974                         c2[2] = f;
8975                         c2[3] = 1;
8976                 }
8977         }
8978 }
8979
8980 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8981 {
8982         int i;
8983         float f;
8984         const float *v;
8985         const float *c;
8986         float *c2;
8987         if (!rsurface.passcolor4f)
8988                 return;
8989         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8990         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8991         rsurface.passcolor4f_vertexbuffer = 0;
8992         rsurface.passcolor4f_bufferoffset = 0;
8993         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)
8994         {
8995                 f = RSurf_FogVertex(v);
8996                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8997                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8998                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8999                 c2[3] = c[3];
9000         }
9001 }
9002
9003 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9004 {
9005         int i;
9006         const float *c;
9007         float *c2;
9008         if (!rsurface.passcolor4f)
9009                 return;
9010         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9011         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9012         rsurface.passcolor4f_vertexbuffer = 0;
9013         rsurface.passcolor4f_bufferoffset = 0;
9014         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9015         {
9016                 c2[0] = c[0] * r;
9017                 c2[1] = c[1] * g;
9018                 c2[2] = c[2] * b;
9019                 c2[3] = c[3] * a;
9020         }
9021 }
9022
9023 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9024 {
9025         int i;
9026         const float *c;
9027         float *c2;
9028         if (!rsurface.passcolor4f)
9029                 return;
9030         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9031         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9032         rsurface.passcolor4f_vertexbuffer = 0;
9033         rsurface.passcolor4f_bufferoffset = 0;
9034         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9035         {
9036                 c2[0] = c[0] + r_refdef.scene.ambient;
9037                 c2[1] = c[1] + r_refdef.scene.ambient;
9038                 c2[2] = c[2] + r_refdef.scene.ambient;
9039                 c2[3] = c[3];
9040         }
9041 }
9042
9043 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9044 {
9045         // TODO: optimize
9046         rsurface.passcolor4f = NULL;
9047         rsurface.passcolor4f_vertexbuffer = 0;
9048         rsurface.passcolor4f_bufferoffset = 0;
9049         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9050         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9051         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9052         GL_Color(r, g, b, a);
9053         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9054         RSurf_DrawBatch();
9055 }
9056
9057 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9058 {
9059         // TODO: optimize applyfog && applycolor case
9060         // just apply fog if necessary, and tint the fog color array if necessary
9061         rsurface.passcolor4f = NULL;
9062         rsurface.passcolor4f_vertexbuffer = 0;
9063         rsurface.passcolor4f_bufferoffset = 0;
9064         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9065         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9066         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9067         GL_Color(r, g, b, a);
9068         RSurf_DrawBatch();
9069 }
9070
9071 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9072 {
9073         // TODO: optimize
9074         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9075         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9076         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9077         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9078         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9079         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9080         GL_Color(r, g, b, a);
9081         RSurf_DrawBatch();
9082 }
9083
9084 static void RSurf_DrawBatch_GL11_ClampColor(void)
9085 {
9086         int i;
9087         const float *c1;
9088         float *c2;
9089         if (!rsurface.passcolor4f)
9090                 return;
9091         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9092         {
9093                 c2[0] = bound(0.0f, c1[0], 1.0f);
9094                 c2[1] = bound(0.0f, c1[1], 1.0f);
9095                 c2[2] = bound(0.0f, c1[2], 1.0f);
9096                 c2[3] = bound(0.0f, c1[3], 1.0f);
9097         }
9098 }
9099
9100 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9101 {
9102         int i;
9103         float f;
9104         const float *v;
9105         const float *n;
9106         float *c;
9107         //vec3_t eyedir;
9108
9109         // fake shading
9110         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9111         rsurface.passcolor4f_vertexbuffer = 0;
9112         rsurface.passcolor4f_bufferoffset = 0;
9113         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)
9114         {
9115                 f = -DotProduct(r_refdef.view.forward, n);
9116                 f = max(0, f);
9117                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9118                 f *= r_refdef.lightmapintensity;
9119                 Vector4Set(c, f, f, f, 1);
9120         }
9121 }
9122
9123 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9124 {
9125         RSurf_DrawBatch_GL11_ApplyFakeLight();
9126         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9127         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9128         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9129         GL_Color(r, g, b, a);
9130         RSurf_DrawBatch();
9131 }
9132
9133 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9134 {
9135         int i;
9136         float f;
9137         float alpha;
9138         const float *v;
9139         const float *n;
9140         float *c;
9141         vec3_t ambientcolor;
9142         vec3_t diffusecolor;
9143         vec3_t lightdir;
9144         // TODO: optimize
9145         // model lighting
9146         VectorCopy(rsurface.modellight_lightdir, lightdir);
9147         f = 0.5f * r_refdef.lightmapintensity;
9148         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9149         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9150         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9151         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9152         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9153         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9154         alpha = *a;
9155         if (VectorLength2(diffusecolor) > 0)
9156         {
9157                 // q3-style directional shading
9158                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9159                 rsurface.passcolor4f_vertexbuffer = 0;
9160                 rsurface.passcolor4f_bufferoffset = 0;
9161                 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)
9162                 {
9163                         if ((f = DotProduct(n, lightdir)) > 0)
9164                                 VectorMA(ambientcolor, f, diffusecolor, c);
9165                         else
9166                                 VectorCopy(ambientcolor, c);
9167                         c[3] = alpha;
9168                 }
9169                 *r = 1;
9170                 *g = 1;
9171                 *b = 1;
9172                 *a = 1;
9173                 *applycolor = false;
9174         }
9175         else
9176         {
9177                 *r = ambientcolor[0];
9178                 *g = ambientcolor[1];
9179                 *b = ambientcolor[2];
9180                 rsurface.passcolor4f = NULL;
9181                 rsurface.passcolor4f_vertexbuffer = 0;
9182                 rsurface.passcolor4f_bufferoffset = 0;
9183         }
9184 }
9185
9186 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9187 {
9188         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9189         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9190         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9191         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9192         GL_Color(r, g, b, a);
9193         RSurf_DrawBatch();
9194 }
9195
9196 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9197 {
9198         int i;
9199         float f;
9200         const float *v;
9201         float *c;
9202
9203         // fake shading
9204         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9205         rsurface.passcolor4f_vertexbuffer = 0;
9206         rsurface.passcolor4f_bufferoffset = 0;
9207
9208         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9209         {
9210                 f = 1 - RSurf_FogVertex(v);
9211                 c[0] = r;
9212                 c[1] = g;
9213                 c[2] = b;
9214                 c[3] = f * a;
9215         }
9216 }
9217
9218 void RSurf_SetupDepthAndCulling(void)
9219 {
9220         // submodels are biased to avoid z-fighting with world surfaces that they
9221         // may be exactly overlapping (avoids z-fighting artifacts on certain
9222         // doors and things in Quake maps)
9223         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9224         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9225         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9226         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9227 }
9228
9229 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9230 {
9231         // transparent sky would be ridiculous
9232         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9233                 return;
9234         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9235         skyrenderlater = true;
9236         RSurf_SetupDepthAndCulling();
9237         GL_DepthMask(true);
9238         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9239         // skymasking on them, and Quake3 never did sky masking (unlike
9240         // software Quake and software Quake2), so disable the sky masking
9241         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9242         // and skymasking also looks very bad when noclipping outside the
9243         // level, so don't use it then either.
9244         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9245         {
9246                 R_Mesh_ResetTextureState();
9247                 if (skyrendermasked)
9248                 {
9249                         R_SetupShader_DepthOrShadow();
9250                         // depth-only (masking)
9251                         GL_ColorMask(0,0,0,0);
9252                         // just to make sure that braindead drivers don't draw
9253                         // anything despite that colormask...
9254                         GL_BlendFunc(GL_ZERO, GL_ONE);
9255                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9256                         if (rsurface.batchvertex3fbuffer)
9257                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9258                         else
9259                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9260                 }
9261                 else
9262                 {
9263                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9264                         // fog sky
9265                         GL_BlendFunc(GL_ONE, GL_ZERO);
9266                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9267                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9268                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9269                 }
9270                 RSurf_DrawBatch();
9271                 if (skyrendermasked)
9272                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9273         }
9274         R_Mesh_ResetTextureState();
9275         GL_Color(1, 1, 1, 1);
9276 }
9277
9278 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9279 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9280 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9281 {
9282         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9283                 return;
9284         if (prepass)
9285         {
9286                 // render screenspace normalmap to texture
9287                 GL_DepthMask(true);
9288                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9289                 RSurf_DrawBatch();
9290                 return;
9291         }
9292
9293         // bind lightmap texture
9294
9295         // water/refraction/reflection/camera surfaces have to be handled specially
9296         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9297         {
9298                 int start, end, startplaneindex;
9299                 for (start = 0;start < texturenumsurfaces;start = end)
9300                 {
9301                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9302                         if(startplaneindex < 0)
9303                         {
9304                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9305                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9306                                 end = start + 1;
9307                                 continue;
9308                         }
9309                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9310                                 ;
9311                         // now that we have a batch using the same planeindex, render it
9312                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9313                         {
9314                                 // render water or distortion background
9315                                 GL_DepthMask(true);
9316                                 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));
9317                                 RSurf_DrawBatch();
9318                                 // blend surface on top
9319                                 GL_DepthMask(false);
9320                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9321                                 RSurf_DrawBatch();
9322                         }
9323                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9324                         {
9325                                 // render surface with reflection texture as input
9326                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9327                                 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));
9328                                 RSurf_DrawBatch();
9329                         }
9330                 }
9331                 return;
9332         }
9333
9334         // render surface batch normally
9335         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9336         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9337         RSurf_DrawBatch();
9338 }
9339
9340 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9341 {
9342         // OpenGL 1.3 path - anything not completely ancient
9343         qboolean applycolor;
9344         qboolean applyfog;
9345         int layerindex;
9346         const texturelayer_t *layer;
9347         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);
9348         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9349
9350         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9351         {
9352                 vec4_t layercolor;
9353                 int layertexrgbscale;
9354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9355                 {
9356                         if (layerindex == 0)
9357                                 GL_AlphaTest(true);
9358                         else
9359                         {
9360                                 GL_AlphaTest(false);
9361                                 GL_DepthFunc(GL_EQUAL);
9362                         }
9363                 }
9364                 GL_DepthMask(layer->depthmask && writedepth);
9365                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9366                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9367                 {
9368                         layertexrgbscale = 4;
9369                         VectorScale(layer->color, 0.25f, layercolor);
9370                 }
9371                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9372                 {
9373                         layertexrgbscale = 2;
9374                         VectorScale(layer->color, 0.5f, layercolor);
9375                 }
9376                 else
9377                 {
9378                         layertexrgbscale = 1;
9379                         VectorScale(layer->color, 1.0f, layercolor);
9380                 }
9381                 layercolor[3] = layer->color[3];
9382                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9383                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9384                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9385                 switch (layer->type)
9386                 {
9387                 case TEXTURELAYERTYPE_LITTEXTURE:
9388                         // single-pass lightmapped texture with 2x rgbscale
9389                         R_Mesh_TexBind(0, r_texture_white);
9390                         R_Mesh_TexMatrix(0, NULL);
9391                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9392                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9393                         R_Mesh_TexBind(1, layer->texture);
9394                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9395                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9396                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9397                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9398                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9399                         else if (FAKELIGHT_ENABLED)
9400                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9401                         else if (rsurface.uselightmaptexture)
9402                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9403                         else
9404                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9405                         break;
9406                 case TEXTURELAYERTYPE_TEXTURE:
9407                         // singletexture unlit texture with transparency support
9408                         R_Mesh_TexBind(0, layer->texture);
9409                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9410                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9411                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9412                         R_Mesh_TexBind(1, 0);
9413                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9414                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9415                         break;
9416                 case TEXTURELAYERTYPE_FOG:
9417                         // singletexture fogging
9418                         if (layer->texture)
9419                         {
9420                                 R_Mesh_TexBind(0, layer->texture);
9421                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9422                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9423                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9424                         }
9425                         else
9426                         {
9427                                 R_Mesh_TexBind(0, 0);
9428                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9429                         }
9430                         R_Mesh_TexBind(1, 0);
9431                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9432                         // generate a color array for the fog pass
9433                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9434                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9435                         RSurf_DrawBatch();
9436                         break;
9437                 default:
9438                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9439                 }
9440         }
9441         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9442         {
9443                 GL_DepthFunc(GL_LEQUAL);
9444                 GL_AlphaTest(false);
9445         }
9446 }
9447
9448 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9449 {
9450         // OpenGL 1.1 - crusty old voodoo path
9451         qboolean applyfog;
9452         int layerindex;
9453         const texturelayer_t *layer;
9454         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);
9455         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9456
9457         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9458         {
9459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9460                 {
9461                         if (layerindex == 0)
9462                                 GL_AlphaTest(true);
9463                         else
9464                         {
9465                                 GL_AlphaTest(false);
9466                                 GL_DepthFunc(GL_EQUAL);
9467                         }
9468                 }
9469                 GL_DepthMask(layer->depthmask && writedepth);
9470                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9471                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9472                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9473                 switch (layer->type)
9474                 {
9475                 case TEXTURELAYERTYPE_LITTEXTURE:
9476                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9477                         {
9478                                 // two-pass lit texture with 2x rgbscale
9479                                 // first the lightmap pass
9480                                 R_Mesh_TexBind(0, r_texture_white);
9481                                 R_Mesh_TexMatrix(0, NULL);
9482                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9483                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9484                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9485                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9486                                 else if (FAKELIGHT_ENABLED)
9487                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9488                                 else if (rsurface.uselightmaptexture)
9489                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9490                                 else
9491                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9492                                 // then apply the texture to it
9493                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9494                                 R_Mesh_TexBind(0, layer->texture);
9495                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9496                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9497                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9498                                 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);
9499                         }
9500                         else
9501                         {
9502                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9503                                 R_Mesh_TexBind(0, layer->texture);
9504                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9505                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9506                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9507                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9508                                         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);
9509                                 else
9510                                         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);
9511                         }
9512                         break;
9513                 case TEXTURELAYERTYPE_TEXTURE:
9514                         // singletexture unlit texture with transparency support
9515                         R_Mesh_TexBind(0, layer->texture);
9516                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9517                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9518                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9519                         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);
9520                         break;
9521                 case TEXTURELAYERTYPE_FOG:
9522                         // singletexture fogging
9523                         if (layer->texture)
9524                         {
9525                                 R_Mesh_TexBind(0, layer->texture);
9526                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9527                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9528                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9529                         }
9530                         else
9531                         {
9532                                 R_Mesh_TexBind(0, 0);
9533                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9534                         }
9535                         // generate a color array for the fog pass
9536                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9537                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9538                         RSurf_DrawBatch();
9539                         break;
9540                 default:
9541                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9542                 }
9543         }
9544         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9545         {
9546                 GL_DepthFunc(GL_LEQUAL);
9547                 GL_AlphaTest(false);
9548         }
9549 }
9550
9551 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9552 {
9553         int vi;
9554         int j;
9555         r_vertexgeneric_t *batchvertex;
9556         float c[4];
9557
9558 //      R_Mesh_ResetTextureState();
9559         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9560
9561         if(rsurface.texture && rsurface.texture->currentskinframe)
9562         {
9563                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9564                 c[3] *= rsurface.texture->currentalpha;
9565         }
9566         else
9567         {
9568                 c[0] = 1;
9569                 c[1] = 0;
9570                 c[2] = 1;
9571                 c[3] = 1;
9572         }
9573
9574         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9575         {
9576                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9577                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9578                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9579         }
9580
9581         // brighten it up (as texture value 127 means "unlit")
9582         c[0] *= 2 * r_refdef.view.colorscale;
9583         c[1] *= 2 * r_refdef.view.colorscale;
9584         c[2] *= 2 * r_refdef.view.colorscale;
9585
9586         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9587                 c[3] *= r_wateralpha.value;
9588
9589         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9590         {
9591                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9592                 GL_DepthMask(false);
9593         }
9594         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9595         {
9596                 GL_BlendFunc(GL_ONE, GL_ONE);
9597                 GL_DepthMask(false);
9598         }
9599         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9600         {
9601                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9602                 GL_DepthMask(false);
9603         }
9604         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9605         {
9606                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9607                 GL_DepthMask(false);
9608         }
9609         else
9610         {
9611                 GL_BlendFunc(GL_ONE, GL_ZERO);
9612                 GL_DepthMask(writedepth);
9613         }
9614
9615         if (r_showsurfaces.integer == 3)
9616         {
9617                 rsurface.passcolor4f = NULL;
9618
9619                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9620                 {
9621                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9622
9623                         rsurface.passcolor4f = NULL;
9624                         rsurface.passcolor4f_vertexbuffer = 0;
9625                         rsurface.passcolor4f_bufferoffset = 0;
9626                 }
9627                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9628                 {
9629                         qboolean applycolor = true;
9630                         float one = 1.0;
9631
9632                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9633
9634                         r_refdef.lightmapintensity = 1;
9635                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9636                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9637                 }
9638                 else if (FAKELIGHT_ENABLED)
9639                 {
9640                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9641
9642                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9643                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9644                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9645                 }
9646                 else
9647                 {
9648                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9649
9650                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9651                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9652                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9653                 }
9654
9655                 if(!rsurface.passcolor4f)
9656                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9657
9658                 RSurf_DrawBatch_GL11_ApplyAmbient();
9659                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9660                 if(r_refdef.fogenabled)
9661                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9662                 RSurf_DrawBatch_GL11_ClampColor();
9663
9664                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9665                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9666                 RSurf_DrawBatch();
9667         }
9668         else if (!r_refdef.view.showdebug)
9669         {
9670                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9671                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9672                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9673                 {
9674                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9675                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9676                 }
9677                 R_Mesh_PrepareVertices_Generic_Unlock();
9678                 RSurf_DrawBatch();
9679         }
9680         else if (r_showsurfaces.integer == 4)
9681         {
9682                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9683                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9684                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9685                 {
9686                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9687                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9688                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9689                 }
9690                 R_Mesh_PrepareVertices_Generic_Unlock();
9691                 RSurf_DrawBatch();
9692         }
9693         else if (r_showsurfaces.integer == 2)
9694         {
9695                 const int *e;
9696                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9697                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9698                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9699                 {
9700                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9701                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9702                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9703                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9704                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9705                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9706                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9707                 }
9708                 R_Mesh_PrepareVertices_Generic_Unlock();
9709                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9710         }
9711         else
9712         {
9713                 int texturesurfaceindex;
9714                 int k;
9715                 const msurface_t *surface;
9716                 float surfacecolor4f[4];
9717                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9718                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9719                 vi = 0;
9720                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9721                 {
9722                         surface = texturesurfacelist[texturesurfaceindex];
9723                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9724                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9725                         for (j = 0;j < surface->num_vertices;j++)
9726                         {
9727                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9728                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9729                                 vi++;
9730                         }
9731                 }
9732                 R_Mesh_PrepareVertices_Generic_Unlock();
9733                 RSurf_DrawBatch();
9734         }
9735 }
9736
9737 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9738 {
9739         CHECKGLERROR
9740         RSurf_SetupDepthAndCulling();
9741         if (r_showsurfaces.integer)
9742         {
9743                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9744                 return;
9745         }
9746         switch (vid.renderpath)
9747         {
9748         case RENDERPATH_GL20:
9749         case RENDERPATH_D3D9:
9750         case RENDERPATH_D3D10:
9751         case RENDERPATH_D3D11:
9752         case RENDERPATH_SOFT:
9753         case RENDERPATH_GLES2:
9754                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9755                 break;
9756         case RENDERPATH_GL13:
9757                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9758                 break;
9759         case RENDERPATH_GL11:
9760                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9761                 break;
9762         }
9763         CHECKGLERROR
9764 }
9765
9766 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9767 {
9768         CHECKGLERROR
9769         RSurf_SetupDepthAndCulling();
9770         if (r_showsurfaces.integer)
9771         {
9772                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9773                 return;
9774         }
9775         switch (vid.renderpath)
9776         {
9777         case RENDERPATH_GL20:
9778         case RENDERPATH_D3D9:
9779         case RENDERPATH_D3D10:
9780         case RENDERPATH_D3D11:
9781         case RENDERPATH_SOFT:
9782         case RENDERPATH_GLES2:
9783                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9784                 break;
9785         case RENDERPATH_GL13:
9786                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9787                 break;
9788         case RENDERPATH_GL11:
9789                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9790                 break;
9791         }
9792         CHECKGLERROR
9793 }
9794
9795 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9796 {
9797         int i, j;
9798         int texturenumsurfaces, endsurface;
9799         texture_t *texture;
9800         const msurface_t *surface;
9801 #define MAXBATCH_TRANSPARENTSURFACES 256
9802         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9803
9804         // if the model is static it doesn't matter what value we give for
9805         // wantnormals and wanttangents, so this logic uses only rules applicable
9806         // to a model, knowing that they are meaningless otherwise
9807         if (ent == r_refdef.scene.worldentity)
9808                 RSurf_ActiveWorldEntity();
9809         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9810                 RSurf_ActiveModelEntity(ent, false, false, false);
9811         else
9812         {
9813                 switch (vid.renderpath)
9814                 {
9815                 case RENDERPATH_GL20:
9816                 case RENDERPATH_D3D9:
9817                 case RENDERPATH_D3D10:
9818                 case RENDERPATH_D3D11:
9819                 case RENDERPATH_SOFT:
9820                 case RENDERPATH_GLES2:
9821                         RSurf_ActiveModelEntity(ent, true, true, false);
9822                         break;
9823                 case RENDERPATH_GL13:
9824                 case RENDERPATH_GL11:
9825                         RSurf_ActiveModelEntity(ent, true, false, false);
9826                         break;
9827                 }
9828         }
9829
9830         if (r_transparentdepthmasking.integer)
9831         {
9832                 qboolean setup = false;
9833                 for (i = 0;i < numsurfaces;i = j)
9834                 {
9835                         j = i + 1;
9836                         surface = rsurface.modelsurfaces + surfacelist[i];
9837                         texture = surface->texture;
9838                         rsurface.texture = R_GetCurrentTexture(texture);
9839                         rsurface.lightmaptexture = NULL;
9840                         rsurface.deluxemaptexture = NULL;
9841                         rsurface.uselightmaptexture = false;
9842                         // scan ahead until we find a different texture
9843                         endsurface = min(i + 1024, numsurfaces);
9844                         texturenumsurfaces = 0;
9845                         texturesurfacelist[texturenumsurfaces++] = surface;
9846                         for (;j < endsurface;j++)
9847                         {
9848                                 surface = rsurface.modelsurfaces + surfacelist[j];
9849                                 if (texture != surface->texture)
9850                                         break;
9851                                 texturesurfacelist[texturenumsurfaces++] = surface;
9852                         }
9853                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9854                                 continue;
9855                         // render the range of surfaces as depth
9856                         if (!setup)
9857                         {
9858                                 setup = true;
9859                                 GL_ColorMask(0,0,0,0);
9860                                 GL_Color(1,1,1,1);
9861                                 GL_DepthTest(true);
9862                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9863                                 GL_DepthMask(true);
9864 //                              R_Mesh_ResetTextureState();
9865                                 R_SetupShader_DepthOrShadow();
9866                         }
9867                         RSurf_SetupDepthAndCulling();
9868                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9869                         if (rsurface.batchvertex3fbuffer)
9870                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9871                         else
9872                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9873                         RSurf_DrawBatch();
9874                 }
9875                 if (setup)
9876                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9877         }
9878
9879         for (i = 0;i < numsurfaces;i = j)
9880         {
9881                 j = i + 1;
9882                 surface = rsurface.modelsurfaces + surfacelist[i];
9883                 texture = surface->texture;
9884                 rsurface.texture = R_GetCurrentTexture(texture);
9885                 // scan ahead until we find a different texture
9886                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9887                 texturenumsurfaces = 0;
9888                 texturesurfacelist[texturenumsurfaces++] = surface;
9889                 if(FAKELIGHT_ENABLED)
9890                 {
9891                         rsurface.lightmaptexture = NULL;
9892                         rsurface.deluxemaptexture = NULL;
9893                         rsurface.uselightmaptexture = false;
9894                         for (;j < endsurface;j++)
9895                         {
9896                                 surface = rsurface.modelsurfaces + surfacelist[j];
9897                                 if (texture != surface->texture)
9898                                         break;
9899                                 texturesurfacelist[texturenumsurfaces++] = surface;
9900                         }
9901                 }
9902                 else
9903                 {
9904                         rsurface.lightmaptexture = surface->lightmaptexture;
9905                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9906                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9907                         for (;j < endsurface;j++)
9908                         {
9909                                 surface = rsurface.modelsurfaces + surfacelist[j];
9910                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9911                                         break;
9912                                 texturesurfacelist[texturenumsurfaces++] = surface;
9913                         }
9914                 }
9915                 // render the range of surfaces
9916                 if (ent == r_refdef.scene.worldentity)
9917                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9918                 else
9919                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9920         }
9921         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9922 }
9923
9924 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9925 {
9926         // transparent surfaces get pushed off into the transparent queue
9927         int surfacelistindex;
9928         const msurface_t *surface;
9929         vec3_t tempcenter, center;
9930         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9931         {
9932                 surface = texturesurfacelist[surfacelistindex];
9933                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9934                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9935                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9936                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9937                 if (queueentity->transparent_offset) // transparent offset
9938                 {
9939                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9940                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9941                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9942                 }
9943                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9944         }
9945 }
9946
9947 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9948 {
9949         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9950                 return;
9951         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9952                 return;
9953         RSurf_SetupDepthAndCulling();
9954         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9955         if (rsurface.batchvertex3fbuffer)
9956                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9957         else
9958                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9959         RSurf_DrawBatch();
9960 }
9961
9962 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9963 {
9964         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9965         CHECKGLERROR
9966         if (depthonly)
9967                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9968         else if (prepass)
9969         {
9970                 if (!rsurface.texture->currentnumlayers)
9971                         return;
9972                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9973                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9974                 else
9975                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9976         }
9977         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9978                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9979         else if (!rsurface.texture->currentnumlayers)
9980                 return;
9981         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9982         {
9983                 // in the deferred case, transparent surfaces were queued during prepass
9984                 if (!r_shadow_usingdeferredprepass)
9985                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9986         }
9987         else
9988         {
9989                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9990                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9991         }
9992         CHECKGLERROR
9993 }
9994
9995 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9996 {
9997         int i, j;
9998         texture_t *texture;
9999         R_FrameData_SetMark();
10000         // break the surface list down into batches by texture and use of lightmapping
10001         for (i = 0;i < numsurfaces;i = j)
10002         {
10003                 j = i + 1;
10004                 // texture is the base texture pointer, rsurface.texture is the
10005                 // current frame/skin the texture is directing us to use (for example
10006                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10007                 // use skin 1 instead)
10008                 texture = surfacelist[i]->texture;
10009                 rsurface.texture = R_GetCurrentTexture(texture);
10010                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10011                 {
10012                         // if this texture is not the kind we want, skip ahead to the next one
10013                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10014                                 ;
10015                         continue;
10016                 }
10017                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10018                 {
10019                         rsurface.lightmaptexture = NULL;
10020                         rsurface.deluxemaptexture = NULL;
10021                         rsurface.uselightmaptexture = false;
10022                         // simply scan ahead until we find a different texture or lightmap state
10023                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10024                                 ;
10025                 }
10026                 else
10027                 {
10028                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10029                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10030                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10031                         // simply scan ahead until we find a different texture or lightmap state
10032                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10033                                 ;
10034                 }
10035                 // render the range of surfaces
10036                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10037         }
10038         R_FrameData_ReturnToMark();
10039 }
10040
10041 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10042 {
10043         CHECKGLERROR
10044         if (depthonly)
10045                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10046         else if (prepass)
10047         {
10048                 if (!rsurface.texture->currentnumlayers)
10049                         return;
10050                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10051                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10052                 else
10053                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10054         }
10055         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10056                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10057         else if (!rsurface.texture->currentnumlayers)
10058                 return;
10059         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10060         {
10061                 // in the deferred case, transparent surfaces were queued during prepass
10062                 if (!r_shadow_usingdeferredprepass)
10063                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10064         }
10065         else
10066         {
10067                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10068                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10069         }
10070         CHECKGLERROR
10071 }
10072
10073 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10074 {
10075         int i, j;
10076         texture_t *texture;
10077         R_FrameData_SetMark();
10078         // break the surface list down into batches by texture and use of lightmapping
10079         for (i = 0;i < numsurfaces;i = j)
10080         {
10081                 j = i + 1;
10082                 // texture is the base texture pointer, rsurface.texture is the
10083                 // current frame/skin the texture is directing us to use (for example
10084                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10085                 // use skin 1 instead)
10086                 texture = surfacelist[i]->texture;
10087                 rsurface.texture = R_GetCurrentTexture(texture);
10088                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10089                 {
10090                         // if this texture is not the kind we want, skip ahead to the next one
10091                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10092                                 ;
10093                         continue;
10094                 }
10095                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10096                 {
10097                         rsurface.lightmaptexture = NULL;
10098                         rsurface.deluxemaptexture = NULL;
10099                         rsurface.uselightmaptexture = false;
10100                         // simply scan ahead until we find a different texture or lightmap state
10101                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10102                                 ;
10103                 }
10104                 else
10105                 {
10106                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10107                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10108                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10109                         // simply scan ahead until we find a different texture or lightmap state
10110                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10111                                 ;
10112                 }
10113                 // render the range of surfaces
10114                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10115         }
10116         R_FrameData_ReturnToMark();
10117 }
10118
10119 float locboxvertex3f[6*4*3] =
10120 {
10121         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10122         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10123         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10124         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10125         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10126         1,0,0, 0,0,0, 0,1,0, 1,1,0
10127 };
10128
10129 unsigned short locboxelements[6*2*3] =
10130 {
10131          0, 1, 2, 0, 2, 3,
10132          4, 5, 6, 4, 6, 7,
10133          8, 9,10, 8,10,11,
10134         12,13,14, 12,14,15,
10135         16,17,18, 16,18,19,
10136         20,21,22, 20,22,23
10137 };
10138
10139 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10140 {
10141         int i, j;
10142         cl_locnode_t *loc = (cl_locnode_t *)ent;
10143         vec3_t mins, size;
10144         float vertex3f[6*4*3];
10145         CHECKGLERROR
10146         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10147         GL_DepthMask(false);
10148         GL_DepthRange(0, 1);
10149         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10150         GL_DepthTest(true);
10151         GL_CullFace(GL_NONE);
10152         R_EntityMatrix(&identitymatrix);
10153
10154 //      R_Mesh_ResetTextureState();
10155
10156         i = surfacelist[0];
10157         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10158                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10159                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10160                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10161
10162         if (VectorCompare(loc->mins, loc->maxs))
10163         {
10164                 VectorSet(size, 2, 2, 2);
10165                 VectorMA(loc->mins, -0.5f, size, mins);
10166         }
10167         else
10168         {
10169                 VectorCopy(loc->mins, mins);
10170                 VectorSubtract(loc->maxs, loc->mins, size);
10171         }
10172
10173         for (i = 0;i < 6*4*3;)
10174                 for (j = 0;j < 3;j++, i++)
10175                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10176
10177         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10178         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10179         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10180 }
10181
10182 void R_DrawLocs(void)
10183 {
10184         int index;
10185         cl_locnode_t *loc, *nearestloc;
10186         vec3_t center;
10187         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10188         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10189         {
10190                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10191                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10192         }
10193 }
10194
10195 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10196 {
10197         if (decalsystem->decals)
10198                 Mem_Free(decalsystem->decals);
10199         memset(decalsystem, 0, sizeof(*decalsystem));
10200 }
10201
10202 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)
10203 {
10204         tridecal_t *decal;
10205         tridecal_t *decals;
10206         int i;
10207
10208         // expand or initialize the system
10209         if (decalsystem->maxdecals <= decalsystem->numdecals)
10210         {
10211                 decalsystem_t old = *decalsystem;
10212                 qboolean useshortelements;
10213                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10214                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10215                 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)));
10216                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10217                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10218                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10219                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10220                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10221                 if (decalsystem->numdecals)
10222                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10223                 if (old.decals)
10224                         Mem_Free(old.decals);
10225                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10226                         decalsystem->element3i[i] = i;
10227                 if (useshortelements)
10228                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10229                                 decalsystem->element3s[i] = i;
10230         }
10231
10232         // grab a decal and search for another free slot for the next one
10233         decals = decalsystem->decals;
10234         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10235         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10236                 ;
10237         decalsystem->freedecal = i;
10238         if (decalsystem->numdecals <= i)
10239                 decalsystem->numdecals = i + 1;
10240
10241         // initialize the decal
10242         decal->lived = 0;
10243         decal->triangleindex = triangleindex;
10244         decal->surfaceindex = surfaceindex;
10245         decal->decalsequence = decalsequence;
10246         decal->color4f[0][0] = c0[0];
10247         decal->color4f[0][1] = c0[1];
10248         decal->color4f[0][2] = c0[2];
10249         decal->color4f[0][3] = 1;
10250         decal->color4f[1][0] = c1[0];
10251         decal->color4f[1][1] = c1[1];
10252         decal->color4f[1][2] = c1[2];
10253         decal->color4f[1][3] = 1;
10254         decal->color4f[2][0] = c2[0];
10255         decal->color4f[2][1] = c2[1];
10256         decal->color4f[2][2] = c2[2];
10257         decal->color4f[2][3] = 1;
10258         decal->vertex3f[0][0] = v0[0];
10259         decal->vertex3f[0][1] = v0[1];
10260         decal->vertex3f[0][2] = v0[2];
10261         decal->vertex3f[1][0] = v1[0];
10262         decal->vertex3f[1][1] = v1[1];
10263         decal->vertex3f[1][2] = v1[2];
10264         decal->vertex3f[2][0] = v2[0];
10265         decal->vertex3f[2][1] = v2[1];
10266         decal->vertex3f[2][2] = v2[2];
10267         decal->texcoord2f[0][0] = t0[0];
10268         decal->texcoord2f[0][1] = t0[1];
10269         decal->texcoord2f[1][0] = t1[0];
10270         decal->texcoord2f[1][1] = t1[1];
10271         decal->texcoord2f[2][0] = t2[0];
10272         decal->texcoord2f[2][1] = t2[1];
10273 }
10274
10275 extern cvar_t cl_decals_bias;
10276 extern cvar_t cl_decals_models;
10277 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10278 // baseparms, parms, temps
10279 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)
10280 {
10281         int cornerindex;
10282         int index;
10283         float v[9][3];
10284         const float *vertex3f;
10285         const float *normal3f;
10286         int numpoints;
10287         float points[2][9][3];
10288         float temp[3];
10289         float tc[9][2];
10290         float f;
10291         float c[9][4];
10292         const int *e;
10293
10294         e = rsurface.modelelement3i + 3*triangleindex;
10295
10296         vertex3f = rsurface.modelvertex3f;
10297         normal3f = rsurface.modelnormal3f;
10298
10299         if (normal3f)
10300         {
10301                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10302                 {
10303                         index = 3*e[cornerindex];
10304                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10305                 }
10306         }
10307         else
10308         {
10309                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10310                 {
10311                         index = 3*e[cornerindex];
10312                         VectorCopy(vertex3f + index, v[cornerindex]);
10313                 }
10314         }
10315
10316         // cull backfaces
10317         //TriangleNormal(v[0], v[1], v[2], normal);
10318         //if (DotProduct(normal, localnormal) < 0.0f)
10319         //      continue;
10320         // clip by each of the box planes formed from the projection matrix
10321         // if anything survives, we emit the decal
10322         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]);
10323         if (numpoints < 3)
10324                 return;
10325         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]);
10326         if (numpoints < 3)
10327                 return;
10328         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]);
10329         if (numpoints < 3)
10330                 return;
10331         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]);
10332         if (numpoints < 3)
10333                 return;
10334         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]);
10335         if (numpoints < 3)
10336                 return;
10337         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]);
10338         if (numpoints < 3)
10339                 return;
10340         // some part of the triangle survived, so we have to accept it...
10341         if (dynamic)
10342         {
10343                 // dynamic always uses the original triangle
10344                 numpoints = 3;
10345                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10346                 {
10347                         index = 3*e[cornerindex];
10348                         VectorCopy(vertex3f + index, v[cornerindex]);
10349                 }
10350         }
10351         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10352         {
10353                 // convert vertex positions to texcoords
10354                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10355                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10356                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10357                 // calculate distance fade from the projection origin
10358                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10359                 f = bound(0.0f, f, 1.0f);
10360                 c[cornerindex][0] = r * f;
10361                 c[cornerindex][1] = g * f;
10362                 c[cornerindex][2] = b * f;
10363                 c[cornerindex][3] = 1.0f;
10364                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10365         }
10366         if (dynamic)
10367                 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);
10368         else
10369                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10370                         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);
10371 }
10372 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)
10373 {
10374         matrix4x4_t projection;
10375         decalsystem_t *decalsystem;
10376         qboolean dynamic;
10377         dp_model_t *model;
10378         const msurface_t *surface;
10379         const msurface_t *surfaces;
10380         const int *surfacelist;
10381         const texture_t *texture;
10382         int numtriangles;
10383         int numsurfacelist;
10384         int surfacelistindex;
10385         int surfaceindex;
10386         int triangleindex;
10387         float localorigin[3];
10388         float localnormal[3];
10389         float localmins[3];
10390         float localmaxs[3];
10391         float localsize;
10392         //float normal[3];
10393         float planes[6][4];
10394         float angles[3];
10395         bih_t *bih;
10396         int bih_triangles_count;
10397         int bih_triangles[256];
10398         int bih_surfaces[256];
10399
10400         decalsystem = &ent->decalsystem;
10401         model = ent->model;
10402         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10403         {
10404                 R_DecalSystem_Reset(&ent->decalsystem);
10405                 return;
10406         }
10407
10408         if (!model->brush.data_leafs && !cl_decals_models.integer)
10409         {
10410                 if (decalsystem->model)
10411                         R_DecalSystem_Reset(decalsystem);
10412                 return;
10413         }
10414
10415         if (decalsystem->model != model)
10416                 R_DecalSystem_Reset(decalsystem);
10417         decalsystem->model = model;
10418
10419         RSurf_ActiveModelEntity(ent, true, false, false);
10420
10421         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10422         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10423         VectorNormalize(localnormal);
10424         localsize = worldsize*rsurface.inversematrixscale;
10425         localmins[0] = localorigin[0] - localsize;
10426         localmins[1] = localorigin[1] - localsize;
10427         localmins[2] = localorigin[2] - localsize;
10428         localmaxs[0] = localorigin[0] + localsize;
10429         localmaxs[1] = localorigin[1] + localsize;
10430         localmaxs[2] = localorigin[2] + localsize;
10431
10432         //VectorCopy(localnormal, planes[4]);
10433         //VectorVectors(planes[4], planes[2], planes[0]);
10434         AnglesFromVectors(angles, localnormal, NULL, false);
10435         AngleVectors(angles, planes[0], planes[2], planes[4]);
10436         VectorNegate(planes[0], planes[1]);
10437         VectorNegate(planes[2], planes[3]);
10438         VectorNegate(planes[4], planes[5]);
10439         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10440         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10441         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10442         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10443         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10444         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10445
10446 #if 1
10447 // works
10448 {
10449         matrix4x4_t forwardprojection;
10450         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10451         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10452 }
10453 #else
10454 // broken
10455 {
10456         float projectionvector[4][3];
10457         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10458         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10459         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10460         projectionvector[0][0] = planes[0][0] * ilocalsize;
10461         projectionvector[0][1] = planes[1][0] * ilocalsize;
10462         projectionvector[0][2] = planes[2][0] * ilocalsize;
10463         projectionvector[1][0] = planes[0][1] * ilocalsize;
10464         projectionvector[1][1] = planes[1][1] * ilocalsize;
10465         projectionvector[1][2] = planes[2][1] * ilocalsize;
10466         projectionvector[2][0] = planes[0][2] * ilocalsize;
10467         projectionvector[2][1] = planes[1][2] * ilocalsize;
10468         projectionvector[2][2] = planes[2][2] * ilocalsize;
10469         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10470         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10471         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10472         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10473 }
10474 #endif
10475
10476         dynamic = model->surfmesh.isanimated;
10477         numsurfacelist = model->nummodelsurfaces;
10478         surfacelist = model->sortedmodelsurfaces;
10479         surfaces = model->data_surfaces;
10480
10481         bih = NULL;
10482         bih_triangles_count = -1;
10483         if(!dynamic)
10484         {
10485                 if(model->render_bih.numleafs)
10486                         bih = &model->render_bih;
10487                 else if(model->collision_bih.numleafs)
10488                         bih = &model->collision_bih;
10489         }
10490         if(bih)
10491                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10492         if(bih_triangles_count == 0)
10493                 return;
10494         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10495                 return;
10496         if(bih_triangles_count > 0)
10497         {
10498                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10499                 {
10500                         surfaceindex = bih_surfaces[triangleindex];
10501                         surface = surfaces + surfaceindex;
10502                         texture = surface->texture;
10503                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10504                                 continue;
10505                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10506                                 continue;
10507                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10508                 }
10509         }
10510         else
10511         {
10512                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10513                 {
10514                         surfaceindex = surfacelist[surfacelistindex];
10515                         surface = surfaces + surfaceindex;
10516                         // check cull box first because it rejects more than any other check
10517                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10518                                 continue;
10519                         // skip transparent surfaces
10520                         texture = surface->texture;
10521                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10522                                 continue;
10523                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10524                                 continue;
10525                         numtriangles = surface->num_triangles;
10526                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10527                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10528                 }
10529         }
10530 }
10531
10532 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10533 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)
10534 {
10535         int renderentityindex;
10536         float worldmins[3];
10537         float worldmaxs[3];
10538         entity_render_t *ent;
10539
10540         if (!cl_decals_newsystem.integer)
10541                 return;
10542
10543         worldmins[0] = worldorigin[0] - worldsize;
10544         worldmins[1] = worldorigin[1] - worldsize;
10545         worldmins[2] = worldorigin[2] - worldsize;
10546         worldmaxs[0] = worldorigin[0] + worldsize;
10547         worldmaxs[1] = worldorigin[1] + worldsize;
10548         worldmaxs[2] = worldorigin[2] + worldsize;
10549
10550         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10551
10552         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10553         {
10554                 ent = r_refdef.scene.entities[renderentityindex];
10555                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10556                         continue;
10557
10558                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10559         }
10560 }
10561
10562 typedef struct r_decalsystem_splatqueue_s
10563 {
10564         vec3_t worldorigin;
10565         vec3_t worldnormal;
10566         float color[4];
10567         float tcrange[4];
10568         float worldsize;
10569         int decalsequence;
10570 }
10571 r_decalsystem_splatqueue_t;
10572
10573 int r_decalsystem_numqueued = 0;
10574 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10575
10576 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)
10577 {
10578         r_decalsystem_splatqueue_t *queue;
10579
10580         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10581                 return;
10582
10583         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10584         VectorCopy(worldorigin, queue->worldorigin);
10585         VectorCopy(worldnormal, queue->worldnormal);
10586         Vector4Set(queue->color, r, g, b, a);
10587         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10588         queue->worldsize = worldsize;
10589         queue->decalsequence = cl.decalsequence++;
10590 }
10591
10592 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10593 {
10594         int i;
10595         r_decalsystem_splatqueue_t *queue;
10596
10597         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10598                 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);
10599         r_decalsystem_numqueued = 0;
10600 }
10601
10602 extern cvar_t cl_decals_max;
10603 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10604 {
10605         int i;
10606         decalsystem_t *decalsystem = &ent->decalsystem;
10607         int numdecals;
10608         int killsequence;
10609         tridecal_t *decal;
10610         float frametime;
10611         float lifetime;
10612
10613         if (!decalsystem->numdecals)
10614                 return;
10615
10616         if (r_showsurfaces.integer)
10617                 return;
10618
10619         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10620         {
10621                 R_DecalSystem_Reset(decalsystem);
10622                 return;
10623         }
10624
10625         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10626         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10627
10628         if (decalsystem->lastupdatetime)
10629                 frametime = (cl.time - decalsystem->lastupdatetime);
10630         else
10631                 frametime = 0;
10632         decalsystem->lastupdatetime = cl.time;
10633         decal = decalsystem->decals;
10634         numdecals = decalsystem->numdecals;
10635
10636         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10637         {
10638                 if (decal->color4f[0][3])
10639                 {
10640                         decal->lived += frametime;
10641                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10642                         {
10643                                 memset(decal, 0, sizeof(*decal));
10644                                 if (decalsystem->freedecal > i)
10645                                         decalsystem->freedecal = i;
10646                         }
10647                 }
10648         }
10649         decal = decalsystem->decals;
10650         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10651                 numdecals--;
10652
10653         // collapse the array by shuffling the tail decals into the gaps
10654         for (;;)
10655         {
10656                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10657                         decalsystem->freedecal++;
10658                 if (decalsystem->freedecal == numdecals)
10659                         break;
10660                 decal[decalsystem->freedecal] = decal[--numdecals];
10661         }
10662
10663         decalsystem->numdecals = numdecals;
10664
10665         if (numdecals <= 0)
10666         {
10667                 // if there are no decals left, reset decalsystem
10668                 R_DecalSystem_Reset(decalsystem);
10669         }
10670 }
10671
10672 extern skinframe_t *decalskinframe;
10673 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10674 {
10675         int i;
10676         decalsystem_t *decalsystem = &ent->decalsystem;
10677         int numdecals;
10678         tridecal_t *decal;
10679         float faderate;
10680         float alpha;
10681         float *v3f;
10682         float *c4f;
10683         float *t2f;
10684         const int *e;
10685         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10686         int numtris = 0;
10687
10688         numdecals = decalsystem->numdecals;
10689         if (!numdecals)
10690                 return;
10691
10692         if (r_showsurfaces.integer)
10693                 return;
10694
10695         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10696         {
10697                 R_DecalSystem_Reset(decalsystem);
10698                 return;
10699         }
10700
10701         // if the model is static it doesn't matter what value we give for
10702         // wantnormals and wanttangents, so this logic uses only rules applicable
10703         // to a model, knowing that they are meaningless otherwise
10704         if (ent == r_refdef.scene.worldentity)
10705                 RSurf_ActiveWorldEntity();
10706         else
10707                 RSurf_ActiveModelEntity(ent, false, false, false);
10708
10709         decalsystem->lastupdatetime = cl.time;
10710         decal = decalsystem->decals;
10711
10712         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10713
10714         // update vertex positions for animated models
10715         v3f = decalsystem->vertex3f;
10716         c4f = decalsystem->color4f;
10717         t2f = decalsystem->texcoord2f;
10718         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10719         {
10720                 if (!decal->color4f[0][3])
10721                         continue;
10722
10723                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10724                         continue;
10725
10726                 // update color values for fading decals
10727                 if (decal->lived >= cl_decals_time.value)
10728                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10729                 else
10730                         alpha = 1.0f;
10731
10732                 c4f[ 0] = decal->color4f[0][0] * alpha;
10733                 c4f[ 1] = decal->color4f[0][1] * alpha;
10734                 c4f[ 2] = decal->color4f[0][2] * alpha;
10735                 c4f[ 3] = 1;
10736                 c4f[ 4] = decal->color4f[1][0] * alpha;
10737                 c4f[ 5] = decal->color4f[1][1] * alpha;
10738                 c4f[ 6] = decal->color4f[1][2] * alpha;
10739                 c4f[ 7] = 1;
10740                 c4f[ 8] = decal->color4f[2][0] * alpha;
10741                 c4f[ 9] = decal->color4f[2][1] * alpha;
10742                 c4f[10] = decal->color4f[2][2] * alpha;
10743                 c4f[11] = 1;
10744
10745                 t2f[0] = decal->texcoord2f[0][0];
10746                 t2f[1] = decal->texcoord2f[0][1];
10747                 t2f[2] = decal->texcoord2f[1][0];
10748                 t2f[3] = decal->texcoord2f[1][1];
10749                 t2f[4] = decal->texcoord2f[2][0];
10750                 t2f[5] = decal->texcoord2f[2][1];
10751
10752                 // update vertex positions for animated models
10753                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10754                 {
10755                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10756                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10757                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10758                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10759                 }
10760                 else
10761                 {
10762                         VectorCopy(decal->vertex3f[0], v3f);
10763                         VectorCopy(decal->vertex3f[1], v3f + 3);
10764                         VectorCopy(decal->vertex3f[2], v3f + 6);
10765                 }
10766
10767                 if (r_refdef.fogenabled)
10768                 {
10769                         alpha = RSurf_FogVertex(v3f);
10770                         VectorScale(c4f, alpha, c4f);
10771                         alpha = RSurf_FogVertex(v3f + 3);
10772                         VectorScale(c4f + 4, alpha, c4f + 4);
10773                         alpha = RSurf_FogVertex(v3f + 6);
10774                         VectorScale(c4f + 8, alpha, c4f + 8);
10775                 }
10776
10777                 v3f += 9;
10778                 c4f += 12;
10779                 t2f += 6;
10780                 numtris++;
10781         }
10782
10783         if (numtris > 0)
10784         {
10785                 r_refdef.stats.drawndecals += numtris;
10786
10787                 // now render the decals all at once
10788                 // (this assumes they all use one particle font texture!)
10789                 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);
10790 //              R_Mesh_ResetTextureState();
10791                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10792                 GL_DepthMask(false);
10793                 GL_DepthRange(0, 1);
10794                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10795                 GL_DepthTest(true);
10796                 GL_CullFace(GL_NONE);
10797                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10798                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10799                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10800         }
10801 }
10802
10803 static void R_DrawModelDecals(void)
10804 {
10805         int i, numdecals;
10806
10807         // fade faster when there are too many decals
10808         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10809         for (i = 0;i < r_refdef.scene.numentities;i++)
10810                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10811
10812         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10813         for (i = 0;i < r_refdef.scene.numentities;i++)
10814                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10815                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10816
10817         R_DecalSystem_ApplySplatEntitiesQueue();
10818
10819         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10820         for (i = 0;i < r_refdef.scene.numentities;i++)
10821                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10822
10823         r_refdef.stats.totaldecals += numdecals;
10824
10825         if (r_showsurfaces.integer)
10826                 return;
10827
10828         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10829
10830         for (i = 0;i < r_refdef.scene.numentities;i++)
10831         {
10832                 if (!r_refdef.viewcache.entityvisible[i])
10833                         continue;
10834                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10835                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10836         }
10837 }
10838
10839 extern cvar_t mod_collision_bih;
10840 void R_DrawDebugModel(void)
10841 {
10842         entity_render_t *ent = rsurface.entity;
10843         int i, j, k, l, flagsmask;
10844         const msurface_t *surface;
10845         dp_model_t *model = ent->model;
10846         vec3_t v;
10847
10848         switch(vid.renderpath)
10849         {
10850         case RENDERPATH_GL11:
10851         case RENDERPATH_GL13:
10852         case RENDERPATH_GL20:
10853                 break;
10854         case RENDERPATH_D3D9:
10855                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10856                 return;
10857         case RENDERPATH_D3D10:
10858                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10859                 return;
10860         case RENDERPATH_D3D11:
10861                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10862                 return;
10863         case RENDERPATH_SOFT:
10864                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10865                 return;
10866         case RENDERPATH_GLES2:
10867                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10868                 return;
10869         }
10870
10871         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10872
10873 //      R_Mesh_ResetTextureState();
10874         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10875         GL_DepthRange(0, 1);
10876         GL_DepthTest(!r_showdisabledepthtest.integer);
10877         GL_DepthMask(false);
10878         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10879
10880         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10881         {
10882                 int triangleindex;
10883                 int bihleafindex;
10884                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10885                 const q3mbrush_t *brush;
10886                 const bih_t *bih = &model->collision_bih;
10887                 const bih_leaf_t *bihleaf;
10888                 float vertex3f[3][3];
10889                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10890                 cullbox = false;
10891                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10892                 {
10893                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10894                                 continue;
10895                         switch (bihleaf->type)
10896                         {
10897                         case BIH_BRUSH:
10898                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10899                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10900                                 {
10901                                         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);
10902                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10903                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10904                                 }
10905                                 break;
10906                         case BIH_COLLISIONTRIANGLE:
10907                                 triangleindex = bihleaf->itemindex;
10908                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10909                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10910                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10911                                 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);
10912                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10913                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10914                                 break;
10915                         case BIH_RENDERTRIANGLE:
10916                                 triangleindex = bihleaf->itemindex;
10917                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10918                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10919                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10920                                 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);
10921                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10922                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10923                                 break;
10924                         }
10925                 }
10926         }
10927
10928         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10929
10930         if (r_showtris.integer || (r_shownormals.value != 0))
10931         {
10932                 if (r_showdisabledepthtest.integer)
10933                 {
10934                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10935                         GL_DepthMask(false);
10936                 }
10937                 else
10938                 {
10939                         GL_BlendFunc(GL_ONE, GL_ZERO);
10940                         GL_DepthMask(true);
10941                 }
10942                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10943                 {
10944                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10945                                 continue;
10946                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10947                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10948                         {
10949                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10950                                 if (r_showtris.value > 0)
10951                                 {
10952                                         if (!rsurface.texture->currentlayers->depthmask)
10953                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10954                                         else if (ent == r_refdef.scene.worldentity)
10955                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10956                                         else
10957                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10958                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10959                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10960                                         RSurf_DrawBatch();
10961                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10962                                         CHECKGLERROR
10963                                 }
10964                                 if (r_shownormals.value < 0)
10965                                 {
10966                                         qglBegin(GL_LINES);
10967                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10968                                         {
10969                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10970                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10971                                                 qglVertex3f(v[0], v[1], v[2]);
10972                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10973                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10974                                                 qglVertex3f(v[0], v[1], v[2]);
10975                                         }
10976                                         qglEnd();
10977                                         CHECKGLERROR
10978                                 }
10979                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10980                                 {
10981                                         qglBegin(GL_LINES);
10982                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10983                                         {
10984                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10985                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10986                                                 qglVertex3f(v[0], v[1], v[2]);
10987                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10988                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10989                                                 qglVertex3f(v[0], v[1], v[2]);
10990                                         }
10991                                         qglEnd();
10992                                         CHECKGLERROR
10993                                         qglBegin(GL_LINES);
10994                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10995                                         {
10996                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10997                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10998                                                 qglVertex3f(v[0], v[1], v[2]);
10999                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11000                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11001                                                 qglVertex3f(v[0], v[1], v[2]);
11002                                         }
11003                                         qglEnd();
11004                                         CHECKGLERROR
11005                                         qglBegin(GL_LINES);
11006                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11007                                         {
11008                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11009                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11010                                                 qglVertex3f(v[0], v[1], v[2]);
11011                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11012                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11013                                                 qglVertex3f(v[0], v[1], v[2]);
11014                                         }
11015                                         qglEnd();
11016                                         CHECKGLERROR
11017                                 }
11018                         }
11019                 }
11020                 rsurface.texture = NULL;
11021         }
11022 }
11023
11024 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11025 int r_maxsurfacelist = 0;
11026 const msurface_t **r_surfacelist = NULL;
11027 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11028 {
11029         int i, j, endj, flagsmask;
11030         dp_model_t *model = r_refdef.scene.worldmodel;
11031         msurface_t *surfaces;
11032         unsigned char *update;
11033         int numsurfacelist = 0;
11034         if (model == NULL)
11035                 return;
11036
11037         if (r_maxsurfacelist < model->num_surfaces)
11038         {
11039                 r_maxsurfacelist = model->num_surfaces;
11040                 if (r_surfacelist)
11041                         Mem_Free((msurface_t**)r_surfacelist);
11042                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11043         }
11044
11045         RSurf_ActiveWorldEntity();
11046
11047         surfaces = model->data_surfaces;
11048         update = model->brushq1.lightmapupdateflags;
11049
11050         // update light styles on this submodel
11051         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11052         {
11053                 model_brush_lightstyleinfo_t *style;
11054                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11055                 {
11056                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11057                         {
11058                                 int *list = style->surfacelist;
11059                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11060                                 for (j = 0;j < style->numsurfaces;j++)
11061                                         update[list[j]] = true;
11062                         }
11063                 }
11064         }
11065
11066         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11067
11068         if (debug)
11069         {
11070                 R_DrawDebugModel();
11071                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11072                 return;
11073         }
11074
11075         rsurface.lightmaptexture = NULL;
11076         rsurface.deluxemaptexture = NULL;
11077         rsurface.uselightmaptexture = false;
11078         rsurface.texture = NULL;
11079         rsurface.rtlight = NULL;
11080         numsurfacelist = 0;
11081         // add visible surfaces to draw list
11082         for (i = 0;i < model->nummodelsurfaces;i++)
11083         {
11084                 j = model->sortedmodelsurfaces[i];
11085                 if (r_refdef.viewcache.world_surfacevisible[j])
11086                         r_surfacelist[numsurfacelist++] = surfaces + j;
11087         }
11088         // update lightmaps if needed
11089         if (model->brushq1.firstrender)
11090         {
11091                 model->brushq1.firstrender = false;
11092                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11093                         if (update[j])
11094                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11095         }
11096         else if (update)
11097         {
11098                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11099                         if (r_refdef.viewcache.world_surfacevisible[j])
11100                                 if (update[j])
11101                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11102         }
11103         // don't do anything if there were no surfaces
11104         if (!numsurfacelist)
11105         {
11106                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11107                 return;
11108         }
11109         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11110
11111         // add to stats if desired
11112         if (r_speeds.integer && !skysurfaces && !depthonly)
11113         {
11114                 r_refdef.stats.world_surfaces += numsurfacelist;
11115                 for (j = 0;j < numsurfacelist;j++)
11116                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11117         }
11118
11119         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11120 }
11121
11122 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11123 {
11124         int i, j, endj, flagsmask;
11125         dp_model_t *model = ent->model;
11126         msurface_t *surfaces;
11127         unsigned char *update;
11128         int numsurfacelist = 0;
11129         if (model == NULL)
11130                 return;
11131
11132         if (r_maxsurfacelist < model->num_surfaces)
11133         {
11134                 r_maxsurfacelist = model->num_surfaces;
11135                 if (r_surfacelist)
11136                         Mem_Free((msurface_t **)r_surfacelist);
11137                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11138         }
11139
11140         // if the model is static it doesn't matter what value we give for
11141         // wantnormals and wanttangents, so this logic uses only rules applicable
11142         // to a model, knowing that they are meaningless otherwise
11143         if (ent == r_refdef.scene.worldentity)
11144                 RSurf_ActiveWorldEntity();
11145         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11146                 RSurf_ActiveModelEntity(ent, false, false, false);
11147         else if (prepass)
11148                 RSurf_ActiveModelEntity(ent, true, true, true);
11149         else if (depthonly)
11150         {
11151                 switch (vid.renderpath)
11152                 {
11153                 case RENDERPATH_GL20:
11154                 case RENDERPATH_D3D9:
11155                 case RENDERPATH_D3D10:
11156                 case RENDERPATH_D3D11:
11157                 case RENDERPATH_SOFT:
11158                 case RENDERPATH_GLES2:
11159                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11160                         break;
11161                 case RENDERPATH_GL13:
11162                 case RENDERPATH_GL11:
11163                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11164                         break;
11165                 }
11166         }
11167         else
11168         {
11169                 switch (vid.renderpath)
11170                 {
11171                 case RENDERPATH_GL20:
11172                 case RENDERPATH_D3D9:
11173                 case RENDERPATH_D3D10:
11174                 case RENDERPATH_D3D11:
11175                 case RENDERPATH_SOFT:
11176                 case RENDERPATH_GLES2:
11177                         RSurf_ActiveModelEntity(ent, true, true, false);
11178                         break;
11179                 case RENDERPATH_GL13:
11180                 case RENDERPATH_GL11:
11181                         RSurf_ActiveModelEntity(ent, true, false, false);
11182                         break;
11183                 }
11184         }
11185
11186         surfaces = model->data_surfaces;
11187         update = model->brushq1.lightmapupdateflags;
11188
11189         // update light styles
11190         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11191         {
11192                 model_brush_lightstyleinfo_t *style;
11193                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11194                 {
11195                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11196                         {
11197                                 int *list = style->surfacelist;
11198                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11199                                 for (j = 0;j < style->numsurfaces;j++)
11200                                         update[list[j]] = true;
11201                         }
11202                 }
11203         }
11204
11205         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11206
11207         if (debug)
11208         {
11209                 R_DrawDebugModel();
11210                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11211                 return;
11212         }
11213
11214         rsurface.lightmaptexture = NULL;
11215         rsurface.deluxemaptexture = NULL;
11216         rsurface.uselightmaptexture = false;
11217         rsurface.texture = NULL;
11218         rsurface.rtlight = NULL;
11219         numsurfacelist = 0;
11220         // add visible surfaces to draw list
11221         for (i = 0;i < model->nummodelsurfaces;i++)
11222                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11223         // don't do anything if there were no surfaces
11224         if (!numsurfacelist)
11225         {
11226                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11227                 return;
11228         }
11229         // update lightmaps if needed
11230         if (update)
11231         {
11232                 int updated = 0;
11233                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11234                 {
11235                         if (update[j])
11236                         {
11237                                 updated++;
11238                                 R_BuildLightMap(ent, surfaces + j);
11239                         }
11240                 }
11241         }
11242         if (update)
11243                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11244                         if (update[j])
11245                                 R_BuildLightMap(ent, surfaces + j);
11246         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11247
11248         // add to stats if desired
11249         if (r_speeds.integer && !skysurfaces && !depthonly)
11250         {
11251                 r_refdef.stats.entities_surfaces += numsurfacelist;
11252                 for (j = 0;j < numsurfacelist;j++)
11253                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11254         }
11255
11256         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11257 }
11258
11259 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11260 {
11261         static texture_t texture;
11262         static msurface_t surface;
11263         const msurface_t *surfacelist = &surface;
11264
11265         // fake enough texture and surface state to render this geometry
11266
11267         texture.update_lastrenderframe = -1; // regenerate this texture
11268         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11269         texture.currentskinframe = skinframe;
11270         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11271         texture.offsetmapping = OFFSETMAPPING_OFF;
11272         texture.offsetscale = 1;
11273         texture.specularscalemod = 1;
11274         texture.specularpowermod = 1;
11275
11276         surface.texture = &texture;
11277         surface.num_triangles = numtriangles;
11278         surface.num_firsttriangle = firsttriangle;
11279         surface.num_vertices = numvertices;
11280         surface.num_firstvertex = firstvertex;
11281
11282         // now render it
11283         rsurface.texture = R_GetCurrentTexture(surface.texture);
11284         rsurface.lightmaptexture = NULL;
11285         rsurface.deluxemaptexture = NULL;
11286         rsurface.uselightmaptexture = false;
11287         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11288 }
11289
11290 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)
11291 {
11292         static msurface_t surface;
11293         const msurface_t *surfacelist = &surface;
11294
11295         // fake enough texture and surface state to render this geometry
11296         surface.texture = texture;
11297         surface.num_triangles = numtriangles;
11298         surface.num_firsttriangle = firsttriangle;
11299         surface.num_vertices = numvertices;
11300         surface.num_firstvertex = firstvertex;
11301
11302         // now render it
11303         rsurface.texture = R_GetCurrentTexture(surface.texture);
11304         rsurface.lightmaptexture = NULL;
11305         rsurface.deluxemaptexture = NULL;
11306         rsurface.uselightmaptexture = false;
11307         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11308 }