]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
6638a3a079f6271ad617d258faac608c68f824e7
[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_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
211
212 extern cvar_t v_glslgamma;
213
214 extern qboolean v_flipped_state;
215
216 static struct r_bloomstate_s
217 {
218         qboolean enabled;
219         qboolean hdr;
220
221         int bloomwidth, bloomheight;
222
223         int screentexturewidth, screentextureheight;
224         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
225
226         int bloomtexturewidth, bloomtextureheight;
227         rtexture_t *texture_bloom;
228
229         // arrays for rendering the screen passes
230         float screentexcoord2f[8];
231         float bloomtexcoord2f[8];
232         float offsettexcoord2f[8];
233
234         r_viewport_t viewport;
235 }
236 r_bloomstate;
237
238 r_waterstate_t r_waterstate;
239
240 /// shadow volume bsp struct with automatically growing nodes buffer
241 svbsp_t r_svbsp;
242
243 rtexture_t *r_texture_blanknormalmap;
244 rtexture_t *r_texture_white;
245 rtexture_t *r_texture_grey128;
246 rtexture_t *r_texture_black;
247 rtexture_t *r_texture_notexture;
248 rtexture_t *r_texture_whitecube;
249 rtexture_t *r_texture_normalizationcube;
250 rtexture_t *r_texture_fogattenuation;
251 rtexture_t *r_texture_fogheighttexture;
252 rtexture_t *r_texture_gammaramps;
253 unsigned int r_texture_gammaramps_serial;
254 //rtexture_t *r_texture_fogintensity;
255 rtexture_t *r_texture_reflectcube;
256
257 // TODO: hash lookups?
258 typedef struct cubemapinfo_s
259 {
260         char basename[64];
261         rtexture_t *texture;
262 }
263 cubemapinfo_t;
264
265 int r_texture_numcubemaps;
266 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
267
268 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
269 unsigned int r_numqueries;
270 unsigned int r_maxqueries;
271
272 typedef struct r_qwskincache_s
273 {
274         char name[MAX_QPATH];
275         skinframe_t *skinframe;
276 }
277 r_qwskincache_t;
278
279 static r_qwskincache_t *r_qwskincache;
280 static int r_qwskincache_size;
281
282 /// vertex coordinates for a quad that covers the screen exactly
283 extern const float r_screenvertex3f[12];
284 extern const float r_d3dscreenvertex3f[12];
285 const float r_screenvertex3f[12] =
286 {
287         0, 0, 0,
288         1, 0, 0,
289         1, 1, 0,
290         0, 1, 0
291 };
292 const float r_d3dscreenvertex3f[12] =
293 {
294         0, 1, 0,
295         1, 1, 0,
296         1, 0, 0,
297         0, 0, 0
298 };
299
300 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
301 {
302         int i;
303         for (i = 0;i < verts;i++)
304         {
305                 out[0] = in[0] * r;
306                 out[1] = in[1] * g;
307                 out[2] = in[2] * b;
308                 out[3] = in[3];
309                 in += 4;
310                 out += 4;
311         }
312 }
313
314 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
315 {
316         int i;
317         for (i = 0;i < verts;i++)
318         {
319                 out[0] = r;
320                 out[1] = g;
321                 out[2] = b;
322                 out[3] = a;
323                 out += 4;
324         }
325 }
326
327 // FIXME: move this to client?
328 void FOG_clear(void)
329 {
330         if (gamemode == GAME_NEHAHRA)
331         {
332                 Cvar_Set("gl_fogenable", "0");
333                 Cvar_Set("gl_fogdensity", "0.2");
334                 Cvar_Set("gl_fogred", "0.3");
335                 Cvar_Set("gl_foggreen", "0.3");
336                 Cvar_Set("gl_fogblue", "0.3");
337         }
338         r_refdef.fog_density = 0;
339         r_refdef.fog_red = 0;
340         r_refdef.fog_green = 0;
341         r_refdef.fog_blue = 0;
342         r_refdef.fog_alpha = 1;
343         r_refdef.fog_start = 0;
344         r_refdef.fog_end = 16384;
345         r_refdef.fog_height = 1<<30;
346         r_refdef.fog_fadedepth = 128;
347         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
348 }
349
350 static void R_BuildBlankTextures(void)
351 {
352         unsigned char data[4];
353         data[2] = 128; // normal X
354         data[1] = 128; // normal Y
355         data[0] = 255; // normal Z
356         data[3] = 128; // height
357         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 255;
359         data[1] = 255;
360         data[2] = 255;
361         data[3] = 255;
362         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 128;
364         data[1] = 128;
365         data[2] = 128;
366         data[3] = 255;
367         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368         data[0] = 0;
369         data[1] = 0;
370         data[2] = 0;
371         data[3] = 255;
372         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
373 }
374
375 static void R_BuildNoTexture(void)
376 {
377         int x, y;
378         unsigned char pix[16][16][4];
379         // this makes a light grey/dark grey checkerboard texture
380         for (y = 0;y < 16;y++)
381         {
382                 for (x = 0;x < 16;x++)
383                 {
384                         if ((y < 8) ^ (x < 8))
385                         {
386                                 pix[y][x][0] = 128;
387                                 pix[y][x][1] = 128;
388                                 pix[y][x][2] = 128;
389                                 pix[y][x][3] = 255;
390                         }
391                         else
392                         {
393                                 pix[y][x][0] = 64;
394                                 pix[y][x][1] = 64;
395                                 pix[y][x][2] = 64;
396                                 pix[y][x][3] = 255;
397                         }
398                 }
399         }
400         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
401 }
402
403 static void R_BuildWhiteCube(void)
404 {
405         unsigned char data[6*1*1*4];
406         memset(data, 255, sizeof(data));
407         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
408 }
409
410 static void R_BuildNormalizationCube(void)
411 {
412         int x, y, side;
413         vec3_t v;
414         vec_t s, t, intensity;
415 #define NORMSIZE 64
416         unsigned char *data;
417         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
418         for (side = 0;side < 6;side++)
419         {
420                 for (y = 0;y < NORMSIZE;y++)
421                 {
422                         for (x = 0;x < NORMSIZE;x++)
423                         {
424                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
425                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
426                                 switch(side)
427                                 {
428                                 default:
429                                 case 0:
430                                         v[0] = 1;
431                                         v[1] = -t;
432                                         v[2] = -s;
433                                         break;
434                                 case 1:
435                                         v[0] = -1;
436                                         v[1] = -t;
437                                         v[2] = s;
438                                         break;
439                                 case 2:
440                                         v[0] = s;
441                                         v[1] = 1;
442                                         v[2] = t;
443                                         break;
444                                 case 3:
445                                         v[0] = s;
446                                         v[1] = -1;
447                                         v[2] = -t;
448                                         break;
449                                 case 4:
450                                         v[0] = s;
451                                         v[1] = -t;
452                                         v[2] = 1;
453                                         break;
454                                 case 5:
455                                         v[0] = -s;
456                                         v[1] = -t;
457                                         v[2] = -1;
458                                         break;
459                                 }
460                                 intensity = 127.0f / sqrt(DotProduct(v, v));
461                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
462                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
463                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
464                                 data[((side*64+y)*64+x)*4+3] = 255;
465                         }
466                 }
467         }
468         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469         Mem_Free(data);
470 }
471
472 static void R_BuildFogTexture(void)
473 {
474         int x, b;
475 #define FOGWIDTH 256
476         unsigned char data1[FOGWIDTH][4];
477         //unsigned char data2[FOGWIDTH][4];
478         double d, r, alpha;
479
480         r_refdef.fogmasktable_start = r_refdef.fog_start;
481         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
482         r_refdef.fogmasktable_range = r_refdef.fogrange;
483         r_refdef.fogmasktable_density = r_refdef.fog_density;
484
485         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
486         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
487         {
488                 d = (x * r - r_refdef.fogmasktable_start);
489                 if(developer_extra.integer)
490                         Con_DPrintf("%f ", d);
491                 d = max(0, d);
492                 if (r_fog_exp2.integer)
493                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
494                 else
495                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
496                 if(developer_extra.integer)
497                         Con_DPrintf(" : %f ", alpha);
498                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
499                 if(developer_extra.integer)
500                         Con_DPrintf(" = %f\n", alpha);
501                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
502         }
503
504         for (x = 0;x < FOGWIDTH;x++)
505         {
506                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
507                 data1[x][0] = b;
508                 data1[x][1] = b;
509                 data1[x][2] = b;
510                 data1[x][3] = 255;
511                 //data2[x][0] = 255 - b;
512                 //data2[x][1] = 255 - b;
513                 //data2[x][2] = 255 - b;
514                 //data2[x][3] = 255;
515         }
516         if (r_texture_fogattenuation)
517         {
518                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
519                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520         }
521         else
522         {
523                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
524                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525         }
526 }
527
528 static void R_BuildFogHeightTexture(void)
529 {
530         unsigned char *inpixels;
531         int size;
532         int x;
533         int y;
534         int j;
535         float c[4];
536         float f;
537         inpixels = NULL;
538         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
539         if (r_refdef.fogheighttexturename[0])
540                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
541         if (!inpixels)
542         {
543                 r_refdef.fog_height_tablesize = 0;
544                 if (r_texture_fogheighttexture)
545                         R_FreeTexture(r_texture_fogheighttexture);
546                 r_texture_fogheighttexture = NULL;
547                 if (r_refdef.fog_height_table2d)
548                         Mem_Free(r_refdef.fog_height_table2d);
549                 r_refdef.fog_height_table2d = NULL;
550                 if (r_refdef.fog_height_table1d)
551                         Mem_Free(r_refdef.fog_height_table1d);
552                 r_refdef.fog_height_table1d = NULL;
553                 return;
554         }
555         size = image_width;
556         r_refdef.fog_height_tablesize = size;
557         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
558         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
559         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
560         Mem_Free(inpixels);
561         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
562         // average fog color table accounting for every fog layer between a point
563         // and the camera.  (Note: attenuation is handled separately!)
564         for (y = 0;y < size;y++)
565         {
566                 for (x = 0;x < size;x++)
567                 {
568                         Vector4Clear(c);
569                         f = 0;
570                         if (x < y)
571                         {
572                                 for (j = x;j <= y;j++)
573                                 {
574                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
575                                         f++;
576                                 }
577                         }
578                         else
579                         {
580                                 for (j = x;j >= y;j--)
581                                 {
582                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
583                                         f++;
584                                 }
585                         }
586                         f = 1.0f / f;
587                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
591                 }
592         }
593         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
594 }
595
596 //=======================================================================================================================================================
597
598 static const char *builtinshaderstring =
599 #include "shader_glsl.h"
600 ;
601
602 const char *builtinhlslshaderstring =
603 #include "shader_hlsl.h"
604 ;
605
606 char *glslshaderstring = NULL;
607 char *hlslshaderstring = NULL;
608
609 //=======================================================================================================================================================
610
611 typedef struct shaderpermutationinfo_s
612 {
613         const char *pretext;
614         const char *name;
615 }
616 shaderpermutationinfo_t;
617
618 typedef struct shadermodeinfo_s
619 {
620         const char *vertexfilename;
621         const char *geometryfilename;
622         const char *fragmentfilename;
623         const char *pretext;
624         const char *name;
625 }
626 shadermodeinfo_t;
627
628 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
629 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
630 {
631         {"#define USEDIFFUSE\n", " diffuse"},
632         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
633         {"#define USEVIEWTINT\n", " viewtint"},
634         {"#define USECOLORMAPPING\n", " colormapping"},
635         {"#define USESATURATION\n", " saturation"},
636         {"#define USEFOGINSIDE\n", " foginside"},
637         {"#define USEFOGOUTSIDE\n", " fogoutside"},
638         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
639         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
640         {"#define USEGAMMARAMPS\n", " gammaramps"},
641         {"#define USECUBEFILTER\n", " cubefilter"},
642         {"#define USEGLOW\n", " glow"},
643         {"#define USEBLOOM\n", " bloom"},
644         {"#define USESPECULAR\n", " specular"},
645         {"#define USEPOSTPROCESSING\n", " postprocessing"},
646         {"#define USEREFLECTION\n", " reflection"},
647         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
648         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
649         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
650         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
651         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
652         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
653         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
654         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
655         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
656         {"#define USEALPHAKILL\n", " alphakill"},
657         {"#define USEREFLECTCUBE\n", " reflectcube"},
658         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
659         {"#define USEBOUNCEGRID\n", " bouncegrid"},
660         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
661 };
662
663 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
664 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
665 {
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
668         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
682 };
683
684 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
685 {
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 };
703
704 struct r_glsl_permutation_s;
705 typedef struct r_glsl_permutation_s
706 {
707         /// hash lookup data
708         struct r_glsl_permutation_s *hashnext;
709         unsigned int mode;
710         unsigned int permutation;
711
712         /// indicates if we have tried compiling this permutation already
713         qboolean compiled;
714         /// 0 if compilation failed
715         int program;
716         // texture units assigned to each detected uniform
717         int tex_Texture_First;
718         int tex_Texture_Second;
719         int tex_Texture_GammaRamps;
720         int tex_Texture_Normal;
721         int tex_Texture_Color;
722         int tex_Texture_Gloss;
723         int tex_Texture_Glow;
724         int tex_Texture_SecondaryNormal;
725         int tex_Texture_SecondaryColor;
726         int tex_Texture_SecondaryGloss;
727         int tex_Texture_SecondaryGlow;
728         int tex_Texture_Pants;
729         int tex_Texture_Shirt;
730         int tex_Texture_FogHeightTexture;
731         int tex_Texture_FogMask;
732         int tex_Texture_Lightmap;
733         int tex_Texture_Deluxemap;
734         int tex_Texture_Attenuation;
735         int tex_Texture_Cube;
736         int tex_Texture_Refraction;
737         int tex_Texture_Reflection;
738         int tex_Texture_ShadowMap2D;
739         int tex_Texture_CubeProjection;
740         int tex_Texture_ScreenDepth;
741         int tex_Texture_ScreenNormalMap;
742         int tex_Texture_ScreenDiffuse;
743         int tex_Texture_ScreenSpecular;
744         int tex_Texture_ReflectMask;
745         int tex_Texture_ReflectCube;
746         int tex_Texture_BounceGrid;
747         /// locations of detected uniforms in program object, or -1 if not found
748         int loc_Texture_First;
749         int loc_Texture_Second;
750         int loc_Texture_GammaRamps;
751         int loc_Texture_Normal;
752         int loc_Texture_Color;
753         int loc_Texture_Gloss;
754         int loc_Texture_Glow;
755         int loc_Texture_SecondaryNormal;
756         int loc_Texture_SecondaryColor;
757         int loc_Texture_SecondaryGloss;
758         int loc_Texture_SecondaryGlow;
759         int loc_Texture_Pants;
760         int loc_Texture_Shirt;
761         int loc_Texture_FogHeightTexture;
762         int loc_Texture_FogMask;
763         int loc_Texture_Lightmap;
764         int loc_Texture_Deluxemap;
765         int loc_Texture_Attenuation;
766         int loc_Texture_Cube;
767         int loc_Texture_Refraction;
768         int loc_Texture_Reflection;
769         int loc_Texture_ShadowMap2D;
770         int loc_Texture_CubeProjection;
771         int loc_Texture_ScreenDepth;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_PixelSize;
804         int loc_ReflectColor;
805         int loc_ReflectFactor;
806         int loc_ReflectOffset;
807         int loc_RefractColor;
808         int loc_Saturation;
809         int loc_ScreenCenterRefractReflect;
810         int loc_ScreenScaleRefractReflect;
811         int loc_ScreenToDepth;
812         int loc_ShadowMap_Parameters;
813         int loc_ShadowMap_TextureScale;
814         int loc_SpecularPower;
815         int loc_UserVec1;
816         int loc_UserVec2;
817         int loc_UserVec3;
818         int loc_UserVec4;
819         int loc_ViewTintColor;
820         int loc_ViewToLight;
821         int loc_ModelToLight;
822         int loc_TexMatrix;
823         int loc_BackgroundTexMatrix;
824         int loc_ModelViewProjectionMatrix;
825         int loc_ModelViewMatrix;
826         int loc_PixelToScreenTexCoord;
827         int loc_ModelToReflectCube;
828         int loc_ShadowMapMatrix;
829         int loc_BloomColorSubtract;
830         int loc_NormalmapScrollBlend;
831         int loc_BounceGridMatrix;
832         int loc_BounceGridIntensity;
833 }
834 r_glsl_permutation_t;
835
836 #define SHADERPERMUTATION_HASHSIZE 256
837
838
839 // non-degradable "lightweight" shader parameters to keep the permutations simpler
840 // these can NOT degrade! only use for simple stuff
841 enum
842 {
843         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
844         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
845         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
846         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
847         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
849 };
850 #define SHADERSTATICPARMS_COUNT 6
851
852 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
853 static int shaderstaticparms_count = 0;
854
855 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
856 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
857 qboolean R_CompileShader_CheckStaticParms(void)
858 {
859         static int r_compileshader_staticparms_save[1];
860         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
861         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
862
863         // detect all
864         if (r_glsl_saturation_redcompensate.integer)
865                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
866         if (r_shadow_glossexact.integer)
867                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
868         if (r_glsl_postprocess.integer)
869         {
870                 if (r_glsl_postprocess_uservec1_enable.integer)
871                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
872                 if (r_glsl_postprocess_uservec2_enable.integer)
873                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
874                 if (r_glsl_postprocess_uservec3_enable.integer)
875                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
876                 if (r_glsl_postprocess_uservec4_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
878         }
879         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
880 }
881
882 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
883         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
884                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
885         else \
886                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
887 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
888 {
889         shaderstaticparms_count = 0;
890
891         // emit all
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
893         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
894         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
895         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
896         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
897         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
898 }
899
900 /// information about each possible shader permutation
901 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
902 /// currently selected permutation
903 r_glsl_permutation_t *r_glsl_permutation;
904 /// storage for permutations linked in the hash table
905 memexpandablearray_t r_glsl_permutationarray;
906
907 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
908 {
909         //unsigned int hashdepth = 0;
910         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
911         r_glsl_permutation_t *p;
912         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
913         {
914                 if (p->mode == mode && p->permutation == permutation)
915                 {
916                         //if (hashdepth > 10)
917                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
918                         return p;
919                 }
920                 //hashdepth++;
921         }
922         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
923         p->mode = mode;
924         p->permutation = permutation;
925         p->hashnext = r_glsl_permutationhash[mode][hashindex];
926         r_glsl_permutationhash[mode][hashindex] = p;
927         //if (hashdepth > 10)
928         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
929         return p;
930 }
931
932 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
933 {
934         char *shaderstring;
935         if (!filename || !filename[0])
936                 return NULL;
937         if (!strcmp(filename, "glsl/default.glsl"))
938         {
939                 if (!glslshaderstring)
940                 {
941                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
942                         if (glslshaderstring)
943                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
944                         else
945                                 glslshaderstring = (char *)builtinshaderstring;
946                 }
947                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
948                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
949                 return shaderstring;
950         }
951         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
952         if (shaderstring)
953         {
954                 if (printfromdisknotice)
955                         Con_DPrintf("from disk %s... ", filename);
956                 return shaderstring;
957         }
958         return shaderstring;
959 }
960
961 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
962 {
963         int i;
964         int sampler;
965         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
966         char *vertexstring, *geometrystring, *fragmentstring;
967         char permutationname[256];
968         int vertstrings_count = 0;
969         int geomstrings_count = 0;
970         int fragstrings_count = 0;
971         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
972         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
973         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
974
975         if (p->compiled)
976                 return;
977         p->compiled = true;
978         p->program = 0;
979
980         permutationname[0] = 0;
981         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
982         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
983         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
984
985         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
986
987         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
988         if(vid.support.gl20shaders130)
989         {
990                 vertstrings_list[vertstrings_count++] = "#version 130\n";
991                 geomstrings_list[geomstrings_count++] = "#version 130\n";
992                 fragstrings_list[fragstrings_count++] = "#version 130\n";
993                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
994                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
995                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
996         }
997
998         // the first pretext is which type of shader to compile as
999         // (later these will all be bound together as a program object)
1000         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1001         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1002         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1003
1004         // the second pretext is the mode (for example a light source)
1005         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1006         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1007         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1008         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1009
1010         // now add all the permutation pretexts
1011         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1012         {
1013                 if (permutation & (1<<i))
1014                 {
1015                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1016                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1017                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1018                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1019                 }
1020                 else
1021                 {
1022                         // keep line numbers correct
1023                         vertstrings_list[vertstrings_count++] = "\n";
1024                         geomstrings_list[geomstrings_count++] = "\n";
1025                         fragstrings_list[fragstrings_count++] = "\n";
1026                 }
1027         }
1028
1029         // add static parms
1030         R_CompileShader_AddStaticParms(mode, permutation);
1031         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1032         vertstrings_count += shaderstaticparms_count;
1033         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1034         geomstrings_count += shaderstaticparms_count;
1035         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1036         fragstrings_count += shaderstaticparms_count;
1037
1038         // now append the shader text itself
1039         vertstrings_list[vertstrings_count++] = vertexstring;
1040         geomstrings_list[geomstrings_count++] = geometrystring;
1041         fragstrings_list[fragstrings_count++] = fragmentstring;
1042
1043         // if any sources were NULL, clear the respective list
1044         if (!vertexstring)
1045                 vertstrings_count = 0;
1046         if (!geometrystring)
1047                 geomstrings_count = 0;
1048         if (!fragmentstring)
1049                 fragstrings_count = 0;
1050
1051         // compile the shader program
1052         if (vertstrings_count + geomstrings_count + fragstrings_count)
1053                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1054         if (p->program)
1055         {
1056                 CHECKGLERROR
1057                 qglUseProgram(p->program);CHECKGLERROR
1058                 // look up all the uniform variable names we care about, so we don't
1059                 // have to look them up every time we set them
1060
1061                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1062                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1063                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1064                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1065                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1066                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1067                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1068                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1069                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1070                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1071                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1072                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1073                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1074                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1075                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1076                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1077                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1078                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1079                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1080                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1081                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1082                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1083                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1084                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1085                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1086                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1087                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1088                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1089                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1090                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1091                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1092                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1093                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1094                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1095                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1096                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1097                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1098                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1099                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1100                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1101                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1102                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1103                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1104                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1105                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1106                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1107                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1108                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1109                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1110                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1111                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1112                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1113                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1114                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1115                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1116                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1117                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1118                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1119                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1120                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1121                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1122                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1123                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1124                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1125                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1126                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1127                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1128                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1129                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1130                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1131                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1132                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1133                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1134                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1135                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1136                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1137                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1138                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1139                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1140                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1141                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1142                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1143                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1144                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1145                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1146                 // initialize the samplers to refer to the texture units we use
1147                 p->tex_Texture_First = -1;
1148                 p->tex_Texture_Second = -1;
1149                 p->tex_Texture_GammaRamps = -1;
1150                 p->tex_Texture_Normal = -1;
1151                 p->tex_Texture_Color = -1;
1152                 p->tex_Texture_Gloss = -1;
1153                 p->tex_Texture_Glow = -1;
1154                 p->tex_Texture_SecondaryNormal = -1;
1155                 p->tex_Texture_SecondaryColor = -1;
1156                 p->tex_Texture_SecondaryGloss = -1;
1157                 p->tex_Texture_SecondaryGlow = -1;
1158                 p->tex_Texture_Pants = -1;
1159                 p->tex_Texture_Shirt = -1;
1160                 p->tex_Texture_FogHeightTexture = -1;
1161                 p->tex_Texture_FogMask = -1;
1162                 p->tex_Texture_Lightmap = -1;
1163                 p->tex_Texture_Deluxemap = -1;
1164                 p->tex_Texture_Attenuation = -1;
1165                 p->tex_Texture_Cube = -1;
1166                 p->tex_Texture_Refraction = -1;
1167                 p->tex_Texture_Reflection = -1;
1168                 p->tex_Texture_ShadowMap2D = -1;
1169                 p->tex_Texture_CubeProjection = -1;
1170                 p->tex_Texture_ScreenDepth = -1;
1171                 p->tex_Texture_ScreenNormalMap = -1;
1172                 p->tex_Texture_ScreenDiffuse = -1;
1173                 p->tex_Texture_ScreenSpecular = -1;
1174                 p->tex_Texture_ReflectMask = -1;
1175                 p->tex_Texture_ReflectCube = -1;
1176                 p->tex_Texture_BounceGrid = -1;
1177                 sampler = 0;
1178                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1179                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1180                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1181                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1182                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1183                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1184                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1185                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1186                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1187                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1188                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1189                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1190                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1191                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1192                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1193                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1194                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1195                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1196                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1197                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1198                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1199                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1200                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1201                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1202                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1203                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1204                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1205                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1206                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1207                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1208                 CHECKGLERROR
1209                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1210         }
1211         else
1212                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1213
1214         // free the strings
1215         if (vertexstring)
1216                 Mem_Free(vertexstring);
1217         if (geometrystring)
1218                 Mem_Free(geometrystring);
1219         if (fragmentstring)
1220                 Mem_Free(fragmentstring);
1221 }
1222
1223 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1224 {
1225         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1226         if (r_glsl_permutation != perm)
1227         {
1228                 r_glsl_permutation = perm;
1229                 if (!r_glsl_permutation->program)
1230                 {
1231                         if (!r_glsl_permutation->compiled)
1232                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1233                         if (!r_glsl_permutation->program)
1234                         {
1235                                 // remove features until we find a valid permutation
1236                                 int i;
1237                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1238                                 {
1239                                         // reduce i more quickly whenever it would not remove any bits
1240                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1241                                         if (!(permutation & j))
1242                                                 continue;
1243                                         permutation -= j;
1244                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1245                                         if (!r_glsl_permutation->compiled)
1246                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1247                                         if (r_glsl_permutation->program)
1248                                                 break;
1249                                 }
1250                                 if (i >= SHADERPERMUTATION_COUNT)
1251                                 {
1252                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1253                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1254                                         qglUseProgram(0);CHECKGLERROR
1255                                         return; // no bit left to clear, entire mode is broken
1256                                 }
1257                         }
1258                 }
1259                 CHECKGLERROR
1260                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1261         }
1262         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1263         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1264         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1265 }
1266
1267 #ifdef SUPPORTD3D
1268
1269 #ifdef SUPPORTD3D
1270 #include <d3d9.h>
1271 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1272 extern D3DCAPS9 vid_d3d9caps;
1273 #endif
1274
1275 struct r_hlsl_permutation_s;
1276 typedef struct r_hlsl_permutation_s
1277 {
1278         /// hash lookup data
1279         struct r_hlsl_permutation_s *hashnext;
1280         unsigned int mode;
1281         unsigned int permutation;
1282
1283         /// indicates if we have tried compiling this permutation already
1284         qboolean compiled;
1285         /// NULL if compilation failed
1286         IDirect3DVertexShader9 *vertexshader;
1287         IDirect3DPixelShader9 *pixelshader;
1288 }
1289 r_hlsl_permutation_t;
1290
1291 typedef enum D3DVSREGISTER_e
1292 {
1293         D3DVSREGISTER_TexMatrix = 0, // float4x4
1294         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1295         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1296         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1297         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1298         D3DVSREGISTER_ModelToLight = 20, // float4x4
1299         D3DVSREGISTER_EyePosition = 24,
1300         D3DVSREGISTER_FogPlane = 25,
1301         D3DVSREGISTER_LightDir = 26,
1302         D3DVSREGISTER_LightPosition = 27,
1303 }
1304 D3DVSREGISTER_t;
1305
1306 typedef enum D3DPSREGISTER_e
1307 {
1308         D3DPSREGISTER_Alpha = 0,
1309         D3DPSREGISTER_BloomBlur_Parameters = 1,
1310         D3DPSREGISTER_ClientTime = 2,
1311         D3DPSREGISTER_Color_Ambient = 3,
1312         D3DPSREGISTER_Color_Diffuse = 4,
1313         D3DPSREGISTER_Color_Specular = 5,
1314         D3DPSREGISTER_Color_Glow = 6,
1315         D3DPSREGISTER_Color_Pants = 7,
1316         D3DPSREGISTER_Color_Shirt = 8,
1317         D3DPSREGISTER_DeferredColor_Ambient = 9,
1318         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1319         D3DPSREGISTER_DeferredColor_Specular = 11,
1320         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1321         D3DPSREGISTER_DeferredMod_Specular = 13,
1322         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1323         D3DPSREGISTER_EyePosition = 15, // unused
1324         D3DPSREGISTER_FogColor = 16,
1325         D3DPSREGISTER_FogHeightFade = 17,
1326         D3DPSREGISTER_FogPlane = 18,
1327         D3DPSREGISTER_FogPlaneViewDist = 19,
1328         D3DPSREGISTER_FogRangeRecip = 20,
1329         D3DPSREGISTER_LightColor = 21,
1330         D3DPSREGISTER_LightDir = 22, // unused
1331         D3DPSREGISTER_LightPosition = 23,
1332         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1333         D3DPSREGISTER_PixelSize = 25,
1334         D3DPSREGISTER_ReflectColor = 26,
1335         D3DPSREGISTER_ReflectFactor = 27,
1336         D3DPSREGISTER_ReflectOffset = 28,
1337         D3DPSREGISTER_RefractColor = 29,
1338         D3DPSREGISTER_Saturation = 30,
1339         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1340         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1341         D3DPSREGISTER_ScreenToDepth = 33,
1342         D3DPSREGISTER_ShadowMap_Parameters = 34,
1343         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1344         D3DPSREGISTER_SpecularPower = 36,
1345         D3DPSREGISTER_UserVec1 = 37,
1346         D3DPSREGISTER_UserVec2 = 38,
1347         D3DPSREGISTER_UserVec3 = 39,
1348         D3DPSREGISTER_UserVec4 = 40,
1349         D3DPSREGISTER_ViewTintColor = 41,
1350         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1351         D3DPSREGISTER_BloomColorSubtract = 43,
1352         D3DPSREGISTER_ViewToLight = 44, // float4x4
1353         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1354         D3DPSREGISTER_NormalmapScrollBlend = 52,
1355         // next at 53
1356 }
1357 D3DPSREGISTER_t;
1358
1359 /// information about each possible shader permutation
1360 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1361 /// currently selected permutation
1362 r_hlsl_permutation_t *r_hlsl_permutation;
1363 /// storage for permutations linked in the hash table
1364 memexpandablearray_t r_hlsl_permutationarray;
1365
1366 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1367 {
1368         //unsigned int hashdepth = 0;
1369         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1370         r_hlsl_permutation_t *p;
1371         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1372         {
1373                 if (p->mode == mode && p->permutation == permutation)
1374                 {
1375                         //if (hashdepth > 10)
1376                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1377                         return p;
1378                 }
1379                 //hashdepth++;
1380         }
1381         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1382         p->mode = mode;
1383         p->permutation = permutation;
1384         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1385         r_hlsl_permutationhash[mode][hashindex] = p;
1386         //if (hashdepth > 10)
1387         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1388         return p;
1389 }
1390
1391 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1392 {
1393         char *shaderstring;
1394         if (!filename || !filename[0])
1395                 return NULL;
1396         if (!strcmp(filename, "hlsl/default.hlsl"))
1397         {
1398                 if (!hlslshaderstring)
1399                 {
1400                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1401                         if (hlslshaderstring)
1402                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1403                         else
1404                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1405                 }
1406                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1407                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1408                 return shaderstring;
1409         }
1410         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1411         if (shaderstring)
1412         {
1413                 if (printfromdisknotice)
1414                         Con_DPrintf("from disk %s... ", filename);
1415                 return shaderstring;
1416         }
1417         return shaderstring;
1418 }
1419
1420 #include <d3dx9.h>
1421 //#include <d3dx9shader.h>
1422 //#include <d3dx9mesh.h>
1423
1424 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1425 {
1426         DWORD *vsbin = NULL;
1427         DWORD *psbin = NULL;
1428         fs_offset_t vsbinsize;
1429         fs_offset_t psbinsize;
1430 //      IDirect3DVertexShader9 *vs = NULL;
1431 //      IDirect3DPixelShader9 *ps = NULL;
1432         ID3DXBuffer *vslog = NULL;
1433         ID3DXBuffer *vsbuffer = NULL;
1434         ID3DXConstantTable *vsconstanttable = NULL;
1435         ID3DXBuffer *pslog = NULL;
1436         ID3DXBuffer *psbuffer = NULL;
1437         ID3DXConstantTable *psconstanttable = NULL;
1438         int vsresult = 0;
1439         int psresult = 0;
1440         char temp[MAX_INPUTLINE];
1441         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1442         qboolean debugshader = gl_paranoid.integer != 0;
1443         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1444         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1445         if (!debugshader)
1446         {
1447                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1448                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1449         }
1450         if ((!vsbin && vertstring) || (!psbin && fragstring))
1451         {
1452                 const char* dllnames_d3dx9 [] =
1453                 {
1454                         "d3dx9_43.dll",
1455                         "d3dx9_42.dll",
1456                         "d3dx9_41.dll",
1457                         "d3dx9_40.dll",
1458                         "d3dx9_39.dll",
1459                         "d3dx9_38.dll",
1460                         "d3dx9_37.dll",
1461                         "d3dx9_36.dll",
1462                         "d3dx9_35.dll",
1463                         "d3dx9_34.dll",
1464                         "d3dx9_33.dll",
1465                         "d3dx9_32.dll",
1466                         "d3dx9_31.dll",
1467                         "d3dx9_30.dll",
1468                         "d3dx9_29.dll",
1469                         "d3dx9_28.dll",
1470                         "d3dx9_27.dll",
1471                         "d3dx9_26.dll",
1472                         "d3dx9_25.dll",
1473                         "d3dx9_24.dll",
1474                         NULL
1475                 };
1476                 dllhandle_t d3dx9_dll = NULL;
1477                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1478                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1479                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1480                 dllfunction_t d3dx9_dllfuncs[] =
1481                 {
1482                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1483                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1484                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1485                         {NULL, NULL}
1486                 };
1487                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1488                 {
1489                         DWORD shaderflags = 0;
1490                         if (debugshader)
1491                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1492                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1493                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1494                         if (vertstring && vertstring[0])
1495                         {
1496                                 if (debugshader)
1497                                 {
1498 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1499 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1500                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1501                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1502                                 }
1503                                 else
1504                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1505                                 if (vsbuffer)
1506                                 {
1507                                         vsbinsize = vsbuffer->GetBufferSize();
1508                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1509                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1510                                         vsbuffer->Release();
1511                                 }
1512                                 if (vslog)
1513                                 {
1514                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1515                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1516                                         vslog->Release();
1517                                 }
1518                         }
1519                         if (fragstring && fragstring[0])
1520                         {
1521                                 if (debugshader)
1522                                 {
1523 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1524 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1525                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1526                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1527                                 }
1528                                 else
1529                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1530                                 if (psbuffer)
1531                                 {
1532                                         psbinsize = psbuffer->GetBufferSize();
1533                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1534                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1535                                         psbuffer->Release();
1536                                 }
1537                                 if (pslog)
1538                                 {
1539                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1540                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1541                                         pslog->Release();
1542                                 }
1543                         }
1544                         Sys_UnloadLibrary(&d3dx9_dll);
1545                 }
1546                 else
1547                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1548         }
1549         if (vsbin && psbin)
1550         {
1551                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1552                 if (FAILED(vsresult))
1553                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1554                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1555                 if (FAILED(psresult))
1556                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1557         }
1558         // free the shader data
1559         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1560         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1561 }
1562
1563 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1564 {
1565         int i;
1566         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1567         int vertstring_length = 0;
1568         int geomstring_length = 0;
1569         int fragstring_length = 0;
1570         char *t;
1571         char *vertexstring, *geometrystring, *fragmentstring;
1572         char *vertstring, *geomstring, *fragstring;
1573         char permutationname[256];
1574         char cachename[256];
1575         int vertstrings_count = 0;
1576         int geomstrings_count = 0;
1577         int fragstrings_count = 0;
1578         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1579         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1580         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1581
1582         if (p->compiled)
1583                 return;
1584         p->compiled = true;
1585         p->vertexshader = NULL;
1586         p->pixelshader = NULL;
1587
1588         permutationname[0] = 0;
1589         cachename[0] = 0;
1590         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1591         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1592         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1593
1594         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1595         strlcat(cachename, "hlsl/", sizeof(cachename));
1596
1597         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1598         vertstrings_count = 0;
1599         geomstrings_count = 0;
1600         fragstrings_count = 0;
1601         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1602         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1603         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1604
1605         // the first pretext is which type of shader to compile as
1606         // (later these will all be bound together as a program object)
1607         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1608         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1609         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1610
1611         // the second pretext is the mode (for example a light source)
1612         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1613         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1614         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1615         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1616         strlcat(cachename, modeinfo->name, sizeof(cachename));
1617
1618         // now add all the permutation pretexts
1619         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1620         {
1621                 if (permutation & (1<<i))
1622                 {
1623                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1624                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1625                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1626                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1627                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1628                 }
1629                 else
1630                 {
1631                         // keep line numbers correct
1632                         vertstrings_list[vertstrings_count++] = "\n";
1633                         geomstrings_list[geomstrings_count++] = "\n";
1634                         fragstrings_list[fragstrings_count++] = "\n";
1635                 }
1636         }
1637
1638         // add static parms
1639         R_CompileShader_AddStaticParms(mode, permutation);
1640         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1641         vertstrings_count += shaderstaticparms_count;
1642         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1643         geomstrings_count += shaderstaticparms_count;
1644         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1645         fragstrings_count += shaderstaticparms_count;
1646
1647         // replace spaces in the cachename with _ characters
1648         for (i = 0;cachename[i];i++)
1649                 if (cachename[i] == ' ')
1650                         cachename[i] = '_';
1651
1652         // now append the shader text itself
1653         vertstrings_list[vertstrings_count++] = vertexstring;
1654         geomstrings_list[geomstrings_count++] = geometrystring;
1655         fragstrings_list[fragstrings_count++] = fragmentstring;
1656
1657         // if any sources were NULL, clear the respective list
1658         if (!vertexstring)
1659                 vertstrings_count = 0;
1660         if (!geometrystring)
1661                 geomstrings_count = 0;
1662         if (!fragmentstring)
1663                 fragstrings_count = 0;
1664
1665         vertstring_length = 0;
1666         for (i = 0;i < vertstrings_count;i++)
1667                 vertstring_length += strlen(vertstrings_list[i]);
1668         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1669         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1670                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1671
1672         geomstring_length = 0;
1673         for (i = 0;i < geomstrings_count;i++)
1674                 geomstring_length += strlen(geomstrings_list[i]);
1675         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1676         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1677                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1678
1679         fragstring_length = 0;
1680         for (i = 0;i < fragstrings_count;i++)
1681                 fragstring_length += strlen(fragstrings_list[i]);
1682         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1683         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1684                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1685
1686         // try to load the cached shader, or generate one
1687         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1688
1689         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1690                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1691         else
1692                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1693
1694         // free the strings
1695         if (vertstring)
1696                 Mem_Free(vertstring);
1697         if (geomstring)
1698                 Mem_Free(geomstring);
1699         if (fragstring)
1700                 Mem_Free(fragstring);
1701         if (vertexstring)
1702                 Mem_Free(vertexstring);
1703         if (geometrystring)
1704                 Mem_Free(geometrystring);
1705         if (fragmentstring)
1706                 Mem_Free(fragmentstring);
1707 }
1708
1709 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1710 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1711 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);}
1712 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);}
1713 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);}
1714 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);}
1715
1716 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1717 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1718 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);}
1719 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);}
1720 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);}
1721 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);}
1722
1723 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1724 {
1725         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1726         if (r_hlsl_permutation != perm)
1727         {
1728                 r_hlsl_permutation = perm;
1729                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1730                 {
1731                         if (!r_hlsl_permutation->compiled)
1732                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1733                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1734                         {
1735                                 // remove features until we find a valid permutation
1736                                 int i;
1737                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1738                                 {
1739                                         // reduce i more quickly whenever it would not remove any bits
1740                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1741                                         if (!(permutation & j))
1742                                                 continue;
1743                                         permutation -= j;
1744                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1745                                         if (!r_hlsl_permutation->compiled)
1746                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1747                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1748                                                 break;
1749                                 }
1750                                 if (i >= SHADERPERMUTATION_COUNT)
1751                                 {
1752                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1753                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1754                                         return; // no bit left to clear, entire mode is broken
1755                                 }
1756                         }
1757                 }
1758                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1759                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1760         }
1761         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1762         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1763         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1764 }
1765 #endif
1766
1767 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1768 {
1769         DPSOFTRAST_SetShader(mode, permutation);
1770         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1771         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1772         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1773 }
1774
1775 void R_GLSL_Restart_f(void)
1776 {
1777         unsigned int i, limit;
1778         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1779                 Mem_Free(glslshaderstring);
1780         glslshaderstring = NULL;
1781         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1782                 Mem_Free(hlslshaderstring);
1783         hlslshaderstring = NULL;
1784         switch(vid.renderpath)
1785         {
1786         case RENDERPATH_D3D9:
1787 #ifdef SUPPORTD3D
1788                 {
1789                         r_hlsl_permutation_t *p;
1790                         r_hlsl_permutation = NULL;
1791                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1792                         for (i = 0;i < limit;i++)
1793                         {
1794                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1795                                 {
1796                                         if (p->vertexshader)
1797                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1798                                         if (p->pixelshader)
1799                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1800                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1801                                 }
1802                         }
1803                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1804                 }
1805 #endif
1806                 break;
1807         case RENDERPATH_D3D10:
1808                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1809                 break;
1810         case RENDERPATH_D3D11:
1811                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1812                 break;
1813         case RENDERPATH_GL20:
1814         case RENDERPATH_GLES2:
1815                 {
1816                         r_glsl_permutation_t *p;
1817                         r_glsl_permutation = NULL;
1818                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1819                         for (i = 0;i < limit;i++)
1820                         {
1821                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1822                                 {
1823                                         GL_Backend_FreeProgram(p->program);
1824                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1825                                 }
1826                         }
1827                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1828                 }
1829                 break;
1830         case RENDERPATH_GL13:
1831         case RENDERPATH_GL11:
1832                 break;
1833         case RENDERPATH_SOFT:
1834                 break;
1835         }
1836 }
1837
1838 void R_GLSL_DumpShader_f(void)
1839 {
1840         int i;
1841         qfile_t *file;
1842
1843         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1844         if (file)
1845         {
1846                 FS_Print(file, "/* The engine may define the following macros:\n");
1847                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1848                 for (i = 0;i < SHADERMODE_COUNT;i++)
1849                         FS_Print(file, glslshadermodeinfo[i].pretext);
1850                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1851                         FS_Print(file, shaderpermutationinfo[i].pretext);
1852                 FS_Print(file, "*/\n");
1853                 FS_Print(file, builtinshaderstring);
1854                 FS_Close(file);
1855                 Con_Printf("glsl/default.glsl written\n");
1856         }
1857         else
1858                 Con_Printf("failed to write to glsl/default.glsl\n");
1859
1860         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1861         if (file)
1862         {
1863                 FS_Print(file, "/* The engine may define the following macros:\n");
1864                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1865                 for (i = 0;i < SHADERMODE_COUNT;i++)
1866                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1867                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1868                         FS_Print(file, shaderpermutationinfo[i].pretext);
1869                 FS_Print(file, "*/\n");
1870                 FS_Print(file, builtinhlslshaderstring);
1871                 FS_Close(file);
1872                 Con_Printf("hlsl/default.hlsl written\n");
1873         }
1874         else
1875                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1876 }
1877
1878 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1879 {
1880         if (!second)
1881                 texturemode = GL_MODULATE;
1882         switch (vid.renderpath)
1883         {
1884         case RENDERPATH_D3D9:
1885 #ifdef SUPPORTD3D
1886                 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))));
1887                 R_Mesh_TexBind(GL20TU_FIRST , first );
1888                 R_Mesh_TexBind(GL20TU_SECOND, second);
1889 #endif
1890                 break;
1891         case RENDERPATH_D3D10:
1892                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1893                 break;
1894         case RENDERPATH_D3D11:
1895                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1896                 break;
1897         case RENDERPATH_GL20:
1898         case RENDERPATH_GLES2:
1899                 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))));
1900                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1901                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1902                 break;
1903         case RENDERPATH_GL13:
1904                 R_Mesh_TexBind(0, first );
1905                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1906                 R_Mesh_TexBind(1, second);
1907                 if (second)
1908                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1909                 break;
1910         case RENDERPATH_GL11:
1911                 R_Mesh_TexBind(0, first );
1912                 break;
1913         case RENDERPATH_SOFT:
1914                 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))));
1915                 R_Mesh_TexBind(GL20TU_FIRST , first );
1916                 R_Mesh_TexBind(GL20TU_SECOND, second);
1917                 break;
1918         }
1919 }
1920
1921 void R_SetupShader_DepthOrShadow(void)
1922 {
1923         switch (vid.renderpath)
1924         {
1925         case RENDERPATH_D3D9:
1926 #ifdef SUPPORTD3D
1927                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1928 #endif
1929                 break;
1930         case RENDERPATH_D3D10:
1931                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1932                 break;
1933         case RENDERPATH_D3D11:
1934                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1935                 break;
1936         case RENDERPATH_GL20:
1937         case RENDERPATH_GLES2:
1938                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1939                 break;
1940         case RENDERPATH_GL13:
1941                 R_Mesh_TexBind(0, 0);
1942                 R_Mesh_TexBind(1, 0);
1943                 break;
1944         case RENDERPATH_GL11:
1945                 R_Mesh_TexBind(0, 0);
1946                 break;
1947         case RENDERPATH_SOFT:
1948                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1949                 break;
1950         }
1951 }
1952
1953 void R_SetupShader_ShowDepth(void)
1954 {
1955         switch (vid.renderpath)
1956         {
1957         case RENDERPATH_D3D9:
1958 #ifdef SUPPORTHLSL
1959                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1960 #endif
1961                 break;
1962         case RENDERPATH_D3D10:
1963                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964                 break;
1965         case RENDERPATH_D3D11:
1966                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1967                 break;
1968         case RENDERPATH_GL20:
1969         case RENDERPATH_GLES2:
1970                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1971                 break;
1972         case RENDERPATH_GL13:
1973                 break;
1974         case RENDERPATH_GL11:
1975                 break;
1976         case RENDERPATH_SOFT:
1977                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1978                 break;
1979         }
1980 }
1981
1982 extern qboolean r_shadow_usingdeferredprepass;
1983 extern cvar_t r_shadow_deferred_8bitrange;
1984 extern rtexture_t *r_shadow_attenuationgradienttexture;
1985 extern rtexture_t *r_shadow_attenuation2dtexture;
1986 extern rtexture_t *r_shadow_attenuation3dtexture;
1987 extern qboolean r_shadow_usingshadowmap2d;
1988 extern qboolean r_shadow_usingshadowmaportho;
1989 extern float r_shadow_shadowmap_texturescale[2];
1990 extern float r_shadow_shadowmap_parameters[4];
1991 extern qboolean r_shadow_shadowmapvsdct;
1992 extern qboolean r_shadow_shadowmapsampler;
1993 extern int r_shadow_shadowmappcf;
1994 extern rtexture_t *r_shadow_shadowmap2dtexture;
1995 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1996 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1997 extern matrix4x4_t r_shadow_shadowmapmatrix;
1998 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1999 extern int r_shadow_prepass_width;
2000 extern int r_shadow_prepass_height;
2001 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2002 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2003 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2004 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2005 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2006
2007 #define BLENDFUNC_ALLOWS_COLORMOD      1
2008 #define BLENDFUNC_ALLOWS_FOG           2
2009 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2010 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2011 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2012 static int R_BlendFuncFlags(int src, int dst)
2013 {
2014         int r = 0;
2015
2016         // a blendfunc allows colormod if:
2017         // a) it can never keep the destination pixel invariant, or
2018         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2019         // this is to prevent unintended side effects from colormod
2020
2021         // a blendfunc allows fog if:
2022         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2023         // this is to prevent unintended side effects from fog
2024
2025         // these checks are the output of fogeval.pl
2026
2027         r |= BLENDFUNC_ALLOWS_COLORMOD;
2028         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2029         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2030         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2031         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2032         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2033         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2034         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2035         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2036         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2037         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2038         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2039         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2040         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2041         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2042         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2043         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2044         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2045         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2046         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2047         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2048         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2049
2050         return r;
2051 }
2052
2053 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)
2054 {
2055         // select a permutation of the lighting shader appropriate to this
2056         // combination of texture, entity, light source, and fogging, only use the
2057         // minimum features necessary to avoid wasting rendering time in the
2058         // fragment shader on features that are not being used
2059         unsigned int permutation = 0;
2060         unsigned int mode = 0;
2061         int blendfuncflags;
2062         static float dummy_colormod[3] = {1, 1, 1};
2063         float *colormod = rsurface.colormod;
2064         float m16f[16];
2065         matrix4x4_t tempmatrix;
2066         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2067         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2068                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2069         if (rsurfacepass == RSURFPASS_BACKGROUND)
2070         {
2071                 // distorted background
2072                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2073                 {
2074                         mode = SHADERMODE_WATER;
2075                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2076                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2077                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2078                         {
2079                                 // this is the right thing to do for wateralpha
2080                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2081                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2082                         }
2083                         else
2084                         {
2085                                 // this is the right thing to do for entity alpha
2086                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2087                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2088                         }
2089                 }
2090                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2091                 {
2092                         mode = SHADERMODE_REFRACTION;
2093                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2094                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2095                 }
2096                 else
2097                 {
2098                         mode = SHADERMODE_GENERIC;
2099                         permutation |= SHADERPERMUTATION_DIFFUSE;
2100                         GL_BlendFunc(GL_ONE, GL_ZERO);
2101                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2102                 }
2103         }
2104         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2105         {
2106                 if (r_glsl_offsetmapping.integer)
2107                 {
2108                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2109                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2110                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2111                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2112                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2113                         {
2114                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2115                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2116                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2117                         }
2118                 }
2119                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2120                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2121                 // normalmap (deferred prepass), may use alpha test on diffuse
2122                 mode = SHADERMODE_DEFERREDGEOMETRY;
2123                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2124                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2125                 GL_BlendFunc(GL_ONE, GL_ZERO);
2126                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2127         }
2128         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2129         {
2130                 if (r_glsl_offsetmapping.integer)
2131                 {
2132                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2133                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2134                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2135                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2136                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2137                         {
2138                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2139                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2140                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2141                         }
2142                 }
2143                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2144                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2145                 // light source
2146                 mode = SHADERMODE_LIGHTSOURCE;
2147                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2148                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2149                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2150                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2151                 if (diffusescale > 0)
2152                         permutation |= SHADERPERMUTATION_DIFFUSE;
2153                 if (specularscale > 0)
2154                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2155                 if (r_refdef.fogenabled)
2156                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2157                 if (rsurface.texture->colormapping)
2158                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2159                 if (r_shadow_usingshadowmap2d)
2160                 {
2161                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2162                         if(r_shadow_shadowmapvsdct)
2163                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2164
2165                         if (r_shadow_shadowmapsampler)
2166                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2167                         if (r_shadow_shadowmappcf > 1)
2168                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2169                         else if (r_shadow_shadowmappcf)
2170                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2171                 }
2172                 if (rsurface.texture->reflectmasktexture)
2173                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2174                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2175                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2176         }
2177         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2178         {
2179                 if (r_glsl_offsetmapping.integer)
2180                 {
2181                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2182                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2183                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2184                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2185                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2186                         {
2187                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2188                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2189                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2190                         }
2191                 }
2192                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2193                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2194                 // unshaded geometry (fullbright or ambient model lighting)
2195                 mode = SHADERMODE_FLATCOLOR;
2196                 ambientscale = diffusescale = specularscale = 0;
2197                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2198                         permutation |= SHADERPERMUTATION_GLOW;
2199                 if (r_refdef.fogenabled)
2200                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2201                 if (rsurface.texture->colormapping)
2202                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2203                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2204                 {
2205                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2206                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2207
2208                         if (r_shadow_shadowmapsampler)
2209                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2210                         if (r_shadow_shadowmappcf > 1)
2211                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2212                         else if (r_shadow_shadowmappcf)
2213                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2214                 }
2215                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2216                         permutation |= SHADERPERMUTATION_REFLECTION;
2217                 if (rsurface.texture->reflectmasktexture)
2218                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2219                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2220                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2221         }
2222         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2223         {
2224                 if (r_glsl_offsetmapping.integer)
2225                 {
2226                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2227                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2228                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2229                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2230                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2231                         {
2232                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2233                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2234                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2235                         }
2236                 }
2237                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2238                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2239                 // directional model lighting
2240                 mode = SHADERMODE_LIGHTDIRECTION;
2241                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2242                         permutation |= SHADERPERMUTATION_GLOW;
2243                 permutation |= SHADERPERMUTATION_DIFFUSE;
2244                 if (specularscale > 0)
2245                         permutation |= SHADERPERMUTATION_SPECULAR;
2246                 if (r_refdef.fogenabled)
2247                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2248                 if (rsurface.texture->colormapping)
2249                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2250                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2251                 {
2252                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2253                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2254
2255                         if (r_shadow_shadowmapsampler)
2256                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2257                         if (r_shadow_shadowmappcf > 1)
2258                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2259                         else if (r_shadow_shadowmappcf)
2260                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2261                 }
2262                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2263                         permutation |= SHADERPERMUTATION_REFLECTION;
2264                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2265                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2266                 if (rsurface.texture->reflectmasktexture)
2267                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2268                 if (r_shadow_bouncegridtexture)
2269                 {
2270                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2271                         if (r_shadow_bouncegriddirectional)
2272                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2273                 }
2274                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2275                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2276         }
2277         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2278         {
2279                 if (r_glsl_offsetmapping.integer)
2280                 {
2281                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2282                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2283                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2284                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2285                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2286                         {
2287                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2288                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2289                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2290                         }
2291                 }
2292                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2293                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2294                 // ambient model lighting
2295                 mode = SHADERMODE_LIGHTDIRECTION;
2296                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2297                         permutation |= SHADERPERMUTATION_GLOW;
2298                 if (r_refdef.fogenabled)
2299                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300                 if (rsurface.texture->colormapping)
2301                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2302                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2303                 {
2304                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2306
2307                         if (r_shadow_shadowmapsampler)
2308                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2309                         if (r_shadow_shadowmappcf > 1)
2310                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2311                         else if (r_shadow_shadowmappcf)
2312                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2313                 }
2314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2315                         permutation |= SHADERPERMUTATION_REFLECTION;
2316                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2317                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2318                 if (rsurface.texture->reflectmasktexture)
2319                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2320                 if (r_shadow_bouncegridtexture)
2321                 {
2322                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2323                         if (r_shadow_bouncegriddirectional)
2324                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2325                 }
2326                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328         }
2329         else
2330         {
2331                 if (r_glsl_offsetmapping.integer)
2332                 {
2333                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2334                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2335                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2336                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2337                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2338                         {
2339                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2340                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2341                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2342                         }
2343                 }
2344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2345                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2346                 // lightmapped wall
2347                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2348                         permutation |= SHADERPERMUTATION_GLOW;
2349                 if (r_refdef.fogenabled)
2350                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2351                 if (rsurface.texture->colormapping)
2352                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2353                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2354                 {
2355                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2356                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2357
2358                         if (r_shadow_shadowmapsampler)
2359                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2360                         if (r_shadow_shadowmappcf > 1)
2361                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2362                         else if (r_shadow_shadowmappcf)
2363                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2364                 }
2365                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2366                         permutation |= SHADERPERMUTATION_REFLECTION;
2367                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2368                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2369                 if (rsurface.texture->reflectmasktexture)
2370                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2371                 if (FAKELIGHT_ENABLED)
2372                 {
2373                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2374                         mode = SHADERMODE_FAKELIGHT;
2375                         permutation |= SHADERPERMUTATION_DIFFUSE;
2376                         if (specularscale > 0)
2377                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2378                 }
2379                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2380                 {
2381                         // deluxemapping (light direction texture)
2382                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2383                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2384                         else
2385                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2386                         permutation |= SHADERPERMUTATION_DIFFUSE;
2387                         if (specularscale > 0)
2388                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2389                 }
2390                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2391                 {
2392                         // fake deluxemapping (uniform light direction in tangentspace)
2393                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2394                         permutation |= SHADERPERMUTATION_DIFFUSE;
2395                         if (specularscale > 0)
2396                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2397                 }
2398                 else if (rsurface.uselightmaptexture)
2399                 {
2400                         // ordinary lightmapping (q1bsp, q3bsp)
2401                         mode = SHADERMODE_LIGHTMAP;
2402                 }
2403                 else
2404                 {
2405                         // ordinary vertex coloring (q3bsp)
2406                         mode = SHADERMODE_VERTEXCOLOR;
2407                 }
2408                 if (r_shadow_bouncegridtexture)
2409                 {
2410                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2411                         if (r_shadow_bouncegriddirectional)
2412                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2413                 }
2414                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2416         }
2417         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2418                 colormod = dummy_colormod;
2419         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2420                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2421         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2422                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2423         switch(vid.renderpath)
2424         {
2425         case RENDERPATH_D3D9:
2426 #ifdef SUPPORTD3D
2427                 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);
2428                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2429                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2430                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2431                 if (mode == SHADERMODE_LIGHTSOURCE)
2432                 {
2433                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2434                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2435                 }
2436                 else
2437                 {
2438                         if (mode == SHADERMODE_LIGHTDIRECTION)
2439                         {
2440                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2441                         }
2442                 }
2443                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2444                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2445                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2446                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2447                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2448
2449                 if (mode == SHADERMODE_LIGHTSOURCE)
2450                 {
2451                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2452                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2453                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2454                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2455                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2456
2457                         // additive passes are only darkened by fog, not tinted
2458                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2459                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2460                 }
2461                 else
2462                 {
2463                         if (mode == SHADERMODE_FLATCOLOR)
2464                         {
2465                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2466                         }
2467                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2468                         {
2469                                 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]);
2470                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2471                                 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);
2472                                 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);
2473                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2474                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2475                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2476                         }
2477                         else
2478                         {
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2481                                 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);
2482                                 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);
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2484                         }
2485                         // additive passes are only darkened by fog, not tinted
2486                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2488                         else
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2490                         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);
2491                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2492                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2493                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2494                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2495                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2496                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2497                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2498                         if (mode == SHADERMODE_WATER)
2499                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2500                 }
2501                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2502                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2503                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2504                 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));
2505                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2506                 if (rsurface.texture->pantstexture)
2507                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2508                 else
2509                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2510                 if (rsurface.texture->shirttexture)
2511                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2512                 else
2513                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2514                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2515                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2516                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2517                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2518                 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));
2519                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2520                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2521
2522                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2523                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2524                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2525                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2526                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2527                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2528                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2529                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2530                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2531                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2532                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2533                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2534                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2535                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2536                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2537                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2538                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2539                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2540                 {
2541                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2542                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2543                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2544                 }
2545                 else
2546                 {
2547                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2548                 }
2549 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2550 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2551                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2552                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2553                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2554                 {
2555                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2556                         if (rsurface.rtlight)
2557                         {
2558                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2559                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2560                         }
2561                 }
2562 #endif
2563                 break;
2564         case RENDERPATH_D3D10:
2565                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2566                 break;
2567         case RENDERPATH_D3D11:
2568                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2569                 break;
2570         case RENDERPATH_GL20:
2571         case RENDERPATH_GLES2:
2572                 if (!vid.useinterleavedarrays)
2573                 {
2574                         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);
2575                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2576                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2577                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2578                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2579                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2580                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2581                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2582                 }
2583                 else
2584                 {
2585                         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);
2586                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2587                 }
2588                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2589                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2590                 if (mode == SHADERMODE_LIGHTSOURCE)
2591                 {
2592                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2593                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2594                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2595                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2596                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2597                         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);
2598         
2599                         // additive passes are only darkened by fog, not tinted
2600                         if (r_glsl_permutation->loc_FogColor >= 0)
2601                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2602                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2603                 }
2604                 else
2605                 {
2606                         if (mode == SHADERMODE_FLATCOLOR)
2607                         {
2608                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2609                         }
2610                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2611                         {
2612                                 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]);
2613                                 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]);
2614                                 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);
2615                                 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);
2616                                 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);
2617                                 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]);
2618                                 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]);
2619                         }
2620                         else
2621                         {
2622                                 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]);
2623                                 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]);
2624                                 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);
2625                                 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);
2626                                 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);
2627                         }
2628                         // additive passes are only darkened by fog, not tinted
2629                         if (r_glsl_permutation->loc_FogColor >= 0)
2630                         {
2631                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2632                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2633                                 else
2634                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2635                         }
2636                         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);
2637                         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]);
2638                         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]);
2639                         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]);
2640                         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]);
2641                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2642                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2643                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2644                         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]);
2645                 }
2646                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2647                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2648                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2649                 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]);
2650                 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]);
2651
2652                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2653                 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));
2654                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2655                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2656                 {
2657                         if (rsurface.texture->pantstexture)
2658                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2659                         else
2660                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2661                 }
2662                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2663                 {
2664                         if (rsurface.texture->shirttexture)
2665                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2666                         else
2667                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2668                 }
2669                 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]);
2670                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2671                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2672                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2673                 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));
2674                 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]);
2675                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2676                 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);}
2677                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2678
2679                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2680                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2681                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2682                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2683                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2684                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2685                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2686                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2687                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2688                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2689                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2690                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2691                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2692                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2693                 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);
2694                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2695                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2696                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2697                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2698                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2699                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2700                 {
2701                         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);
2702                         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);
2703                         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);
2704                 }
2705                 else
2706                 {
2707                         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);
2708                 }
2709                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2710                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2711                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2712                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2713                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2714                 {
2715                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2716                         if (rsurface.rtlight)
2717                         {
2718                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2719                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2720                         }
2721                 }
2722                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2723                 CHECKGLERROR
2724                 break;
2725         case RENDERPATH_GL13:
2726         case RENDERPATH_GL11:
2727                 break;
2728         case RENDERPATH_SOFT:
2729                 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);
2730                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2731                 R_SetupShader_SetPermutationSoft(mode, permutation);
2732                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2733                 if (mode == SHADERMODE_LIGHTSOURCE)
2734                 {
2735                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2736                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2737                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2738                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2739                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2740                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2741         
2742                         // additive passes are only darkened by fog, not tinted
2743                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2744                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2745                 }
2746                 else
2747                 {
2748                         if (mode == SHADERMODE_FLATCOLOR)
2749                         {
2750                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2751                         }
2752                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2753                         {
2754                                 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]);
2755                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2756                                 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);
2757                                 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);
2758                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2759                                 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]);
2760                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2761                         }
2762                         else
2763                         {
2764                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2765                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2766                                 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);
2767                                 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);
2768                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2769                         }
2770                         // additive passes are only darkened by fog, not tinted
2771                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2773                         else
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2775                         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);
2776                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2777                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2778                         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]);
2779                         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]);
2780                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2781                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2782                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2783                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2784                 }
2785                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2786                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2787                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2788                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2789                 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]);
2790
2791                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2792                 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));
2793                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2794                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2795                 {
2796                         if (rsurface.texture->pantstexture)
2797                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2798                         else
2799                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2800                 }
2801                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2802                 {
2803                         if (rsurface.texture->shirttexture)
2804                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2805                         else
2806                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2807                 }
2808                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2809                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2810                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2811                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2812                 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));
2813                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2814                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2815
2816                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2817                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2818                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2819                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2820                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2821                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2822                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2823                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2824                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2825                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2826                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2827                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2828                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2829                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2830                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2831                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2832                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2833                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2834                 {
2835                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2836                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2837                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2838                 }
2839                 else
2840                 {
2841                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2842                 }
2843 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2844 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2845                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2846                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2847                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2848                 {
2849                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2850                         if (rsurface.rtlight)
2851                         {
2852                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2853                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2854                         }
2855                 }
2856                 break;
2857         }
2858 }
2859
2860 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2861 {
2862         // select a permutation of the lighting shader appropriate to this
2863         // combination of texture, entity, light source, and fogging, only use the
2864         // minimum features necessary to avoid wasting rendering time in the
2865         // fragment shader on features that are not being used
2866         unsigned int permutation = 0;
2867         unsigned int mode = 0;
2868         const float *lightcolorbase = rtlight->currentcolor;
2869         float ambientscale = rtlight->ambientscale;
2870         float diffusescale = rtlight->diffusescale;
2871         float specularscale = rtlight->specularscale;
2872         // this is the location of the light in view space
2873         vec3_t viewlightorigin;
2874         // this transforms from view space (camera) to light space (cubemap)
2875         matrix4x4_t viewtolight;
2876         matrix4x4_t lighttoview;
2877         float viewtolight16f[16];
2878         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2879         // light source
2880         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2881         if (rtlight->currentcubemap != r_texture_whitecube)
2882                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2883         if (diffusescale > 0)
2884                 permutation |= SHADERPERMUTATION_DIFFUSE;
2885         if (specularscale > 0)
2886                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2887         if (r_shadow_usingshadowmap2d)
2888         {
2889                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2890                 if (r_shadow_shadowmapvsdct)
2891                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2892
2893                 if (r_shadow_shadowmapsampler)
2894                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2895                 if (r_shadow_shadowmappcf > 1)
2896                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2897                 else if (r_shadow_shadowmappcf)
2898                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2899         }
2900         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2901         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2902         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2903         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2904         switch(vid.renderpath)
2905         {
2906         case RENDERPATH_D3D9:
2907 #ifdef SUPPORTD3D
2908                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2909                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2910                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2911                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2912                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2913                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2914                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2915                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2916                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2917                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2918                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2919
2920                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2921                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2922                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2923                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2924                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2925                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2926 #endif
2927                 break;
2928         case RENDERPATH_D3D10:
2929                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2930                 break;
2931         case RENDERPATH_D3D11:
2932                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2933                 break;
2934         case RENDERPATH_GL20:
2935         case RENDERPATH_GLES2:
2936                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2937                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2938                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2939                 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);
2940                 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);
2941                 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);
2942                 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]);
2943                 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]);
2944                 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));
2945                 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]);
2946                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2947
2948                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2949                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2950                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2951                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2952                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2953                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2954                 break;
2955         case RENDERPATH_GL13:
2956         case RENDERPATH_GL11:
2957                 break;
2958         case RENDERPATH_SOFT:
2959                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2960                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2961                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2962                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2963                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2964                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2965                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2966                 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]);
2967                 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));
2968                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2969                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2970
2971                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2972                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2973                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2974                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2975                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2976                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2977                 break;
2978         }
2979 }
2980
2981 #define SKINFRAME_HASH 1024
2982
2983 typedef struct
2984 {
2985         int loadsequence; // incremented each level change
2986         memexpandablearray_t array;
2987         skinframe_t *hash[SKINFRAME_HASH];
2988 }
2989 r_skinframe_t;
2990 r_skinframe_t r_skinframe;
2991
2992 void R_SkinFrame_PrepareForPurge(void)
2993 {
2994         r_skinframe.loadsequence++;
2995         // wrap it without hitting zero
2996         if (r_skinframe.loadsequence >= 200)
2997                 r_skinframe.loadsequence = 1;
2998 }
2999
3000 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3001 {
3002         if (!skinframe)
3003                 return;
3004         // mark the skinframe as used for the purging code
3005         skinframe->loadsequence = r_skinframe.loadsequence;
3006 }
3007
3008 void R_SkinFrame_Purge(void)
3009 {
3010         int i;
3011         skinframe_t *s;
3012         for (i = 0;i < SKINFRAME_HASH;i++)
3013         {
3014                 for (s = r_skinframe.hash[i];s;s = s->next)
3015                 {
3016                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3017                         {
3018                                 if (s->merged == s->base)
3019                                         s->merged = NULL;
3020                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3021                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3022                                 R_PurgeTexture(s->merged);s->merged = NULL;
3023                                 R_PurgeTexture(s->base  );s->base   = NULL;
3024                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3025                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3026                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3027                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3028                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3029                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3030                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3031                                 s->loadsequence = 0;
3032                         }
3033                 }
3034         }
3035 }
3036
3037 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3038         skinframe_t *item;
3039         char basename[MAX_QPATH];
3040
3041         Image_StripImageExtension(name, basename, sizeof(basename));
3042
3043         if( last == NULL ) {
3044                 int hashindex;
3045                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3046                 item = r_skinframe.hash[hashindex];
3047         } else {
3048                 item = last->next;
3049         }
3050
3051         // linearly search through the hash bucket
3052         for( ; item ; item = item->next ) {
3053                 if( !strcmp( item->basename, basename ) ) {
3054                         return item;
3055                 }
3056         }
3057         return NULL;
3058 }
3059
3060 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3061 {
3062         skinframe_t *item;
3063         int hashindex;
3064         char basename[MAX_QPATH];
3065
3066         Image_StripImageExtension(name, basename, sizeof(basename));
3067
3068         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3069         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3070                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3071                         break;
3072
3073         if (!item) {
3074                 rtexture_t *dyntexture;
3075                 // check whether its a dynamic texture
3076                 dyntexture = CL_GetDynTexture( basename );
3077                 if (!add && !dyntexture)
3078                         return NULL;
3079                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3080                 memset(item, 0, sizeof(*item));
3081                 strlcpy(item->basename, basename, sizeof(item->basename));
3082                 item->base = dyntexture; // either NULL or dyntexture handle
3083                 item->textureflags = textureflags;
3084                 item->comparewidth = comparewidth;
3085                 item->compareheight = compareheight;
3086                 item->comparecrc = comparecrc;
3087                 item->next = r_skinframe.hash[hashindex];
3088                 r_skinframe.hash[hashindex] = item;
3089         }
3090         else if( item->base == NULL )
3091         {
3092                 rtexture_t *dyntexture;
3093                 // check whether its a dynamic texture
3094                 // 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]
3095                 dyntexture = CL_GetDynTexture( basename );
3096                 item->base = dyntexture; // either NULL or dyntexture handle
3097         }
3098
3099         R_SkinFrame_MarkUsed(item);
3100         return item;
3101 }
3102
3103 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3104         { \
3105                 unsigned long long avgcolor[5], wsum; \
3106                 int pix, comp, w; \
3107                 avgcolor[0] = 0; \
3108                 avgcolor[1] = 0; \
3109                 avgcolor[2] = 0; \
3110                 avgcolor[3] = 0; \
3111                 avgcolor[4] = 0; \
3112                 wsum = 0; \
3113                 for(pix = 0; pix < cnt; ++pix) \
3114                 { \
3115                         w = 0; \
3116                         for(comp = 0; comp < 3; ++comp) \
3117                                 w += getpixel; \
3118                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3119                         { \
3120                                 ++wsum; \
3121                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3122                                 w = getpixel; \
3123                                 for(comp = 0; comp < 3; ++comp) \
3124                                         avgcolor[comp] += getpixel * w; \
3125                                 avgcolor[3] += w; \
3126                         } \
3127                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3128                         avgcolor[4] += getpixel; \
3129                 } \
3130                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3131                         avgcolor[3] = 1; \
3132                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3133                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3134                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3135                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3136         }
3137
3138 extern cvar_t gl_picmip;
3139 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3140 {
3141         int j;
3142         unsigned char *pixels;
3143         unsigned char *bumppixels;
3144         unsigned char *basepixels = NULL;
3145         int basepixels_width = 0;
3146         int basepixels_height = 0;
3147         skinframe_t *skinframe;
3148         rtexture_t *ddsbase = NULL;
3149         qboolean ddshasalpha = false;
3150         float ddsavgcolor[4];
3151         char basename[MAX_QPATH];
3152         int miplevel = R_PicmipForFlags(textureflags);
3153         int savemiplevel = miplevel;
3154         int mymiplevel;
3155
3156         if (cls.state == ca_dedicated)
3157                 return NULL;
3158
3159         // return an existing skinframe if already loaded
3160         // if loading of the first image fails, don't make a new skinframe as it
3161         // would cause all future lookups of this to be missing
3162         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3163         if (skinframe && skinframe->base)
3164                 return skinframe;
3165
3166         Image_StripImageExtension(name, basename, sizeof(basename));
3167
3168         // check for DDS texture file first
3169         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3170         {
3171                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3172                 if (basepixels == NULL)
3173                         return NULL;
3174         }
3175
3176         // FIXME handle miplevel
3177
3178         if (developer_loading.integer)
3179                 Con_Printf("loading skin \"%s\"\n", name);
3180
3181         // we've got some pixels to store, so really allocate this new texture now
3182         if (!skinframe)
3183                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3184         skinframe->stain = NULL;
3185         skinframe->merged = NULL;
3186         skinframe->base = NULL;
3187         skinframe->pants = NULL;
3188         skinframe->shirt = NULL;
3189         skinframe->nmap = NULL;
3190         skinframe->gloss = NULL;
3191         skinframe->glow = NULL;
3192         skinframe->fog = NULL;
3193         skinframe->reflect = NULL;
3194         skinframe->hasalpha = false;
3195
3196         if (ddsbase)
3197         {
3198                 skinframe->base = ddsbase;
3199                 skinframe->hasalpha = ddshasalpha;
3200                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3201                 if (r_loadfog && skinframe->hasalpha)
3202                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3203                 //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]);
3204         }
3205         else
3206         {
3207                 basepixels_width = image_width;
3208                 basepixels_height = image_height;
3209                 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);
3210                 if (textureflags & TEXF_ALPHA)
3211                 {
3212                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3213                         {
3214                                 if (basepixels[j] < 255)
3215                                 {
3216                                         skinframe->hasalpha = true;
3217                                         break;
3218                                 }
3219                         }
3220                         if (r_loadfog && skinframe->hasalpha)
3221                         {
3222                                 // has transparent pixels
3223                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3224                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3225                                 {
3226                                         pixels[j+0] = 255;
3227                                         pixels[j+1] = 255;
3228                                         pixels[j+2] = 255;
3229                                         pixels[j+3] = basepixels[j+3];
3230                                 }
3231                                 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);
3232                                 Mem_Free(pixels);
3233                         }
3234                 }
3235                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3236                 //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]);
3237                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3238                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3239                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3240                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3241         }
3242
3243         if (r_loaddds)
3244         {
3245                 mymiplevel = savemiplevel;
3246                 if (r_loadnormalmap)
3247                         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);
3248                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3249                 if (r_loadgloss)
3250                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3251                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3252                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3253                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3254         }
3255
3256         // _norm is the name used by tenebrae and has been adopted as standard
3257         if (r_loadnormalmap && skinframe->nmap == NULL)
3258         {
3259                 mymiplevel = savemiplevel;
3260                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3261                 {
3262                         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);
3263                         Mem_Free(pixels);
3264                         pixels = NULL;
3265                 }
3266                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3267                 {
3268                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3269                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3270                         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);
3271                         Mem_Free(pixels);
3272                         Mem_Free(bumppixels);
3273                 }
3274                 else if (r_shadow_bumpscale_basetexture.value > 0)
3275                 {
3276                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3277                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3278                         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);
3279                         Mem_Free(pixels);
3280                 }
3281                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3282                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3283         }
3284
3285         // _luma is supported only for tenebrae compatibility
3286         // _glow is the preferred name
3287         mymiplevel = savemiplevel;
3288         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))))
3289         {
3290                 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);
3291                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3292                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3293                 Mem_Free(pixels);pixels = NULL;
3294         }
3295
3296         mymiplevel = savemiplevel;
3297         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3298         {
3299                 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);
3300                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3301                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3302                 Mem_Free(pixels);
3303                 pixels = NULL;
3304         }
3305
3306         mymiplevel = savemiplevel;
3307         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3308         {
3309                 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);
3310                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3311                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3312                 Mem_Free(pixels);
3313                 pixels = NULL;
3314         }
3315
3316         mymiplevel = savemiplevel;
3317         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3318         {
3319                 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);
3320                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3321                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3322                 Mem_Free(pixels);
3323                 pixels = NULL;
3324         }
3325
3326         mymiplevel = savemiplevel;
3327         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3328         {
3329                 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);
3330                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3331                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3332                 Mem_Free(pixels);
3333                 pixels = NULL;
3334         }
3335
3336         if (basepixels)
3337                 Mem_Free(basepixels);
3338
3339         return skinframe;
3340 }
3341
3342 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3343 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3344 {
3345         int i;
3346         unsigned char *temp1, *temp2;
3347         skinframe_t *skinframe;
3348
3349         if (cls.state == ca_dedicated)
3350                 return NULL;
3351
3352         // if already loaded just return it, otherwise make a new skinframe
3353         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3354         if (skinframe && skinframe->base)
3355                 return skinframe;
3356
3357         skinframe->stain = NULL;
3358         skinframe->merged = NULL;
3359         skinframe->base = NULL;
3360         skinframe->pants = NULL;
3361         skinframe->shirt = NULL;
3362         skinframe->nmap = NULL;
3363         skinframe->gloss = NULL;
3364         skinframe->glow = NULL;
3365         skinframe->fog = NULL;
3366         skinframe->reflect = NULL;
3367         skinframe->hasalpha = false;
3368
3369         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3370         if (!skindata)
3371                 return NULL;
3372
3373         if (developer_loading.integer)
3374                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3375
3376         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3377         {
3378                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3379                 temp2 = temp1 + width * height * 4;
3380                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3381                 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);
3382                 Mem_Free(temp1);
3383         }
3384         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3385         if (textureflags & TEXF_ALPHA)
3386         {
3387                 for (i = 3;i < width * height * 4;i += 4)
3388                 {
3389                         if (skindata[i] < 255)
3390                         {
3391                                 skinframe->hasalpha = true;
3392                                 break;
3393                         }
3394                 }
3395                 if (r_loadfog && skinframe->hasalpha)
3396                 {
3397                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3398                         memcpy(fogpixels, skindata, width * height * 4);
3399                         for (i = 0;i < width * height * 4;i += 4)
3400                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3401                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3402                         Mem_Free(fogpixels);
3403                 }
3404         }
3405
3406         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3407         //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]);
3408
3409         return skinframe;
3410 }
3411
3412 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3413 {
3414         int i;
3415         int featuresmask;
3416         skinframe_t *skinframe;
3417
3418         if (cls.state == ca_dedicated)
3419                 return NULL;
3420
3421         // if already loaded just return it, otherwise make a new skinframe
3422         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3423         if (skinframe && skinframe->base)
3424                 return skinframe;
3425
3426         skinframe->stain = NULL;
3427         skinframe->merged = NULL;
3428         skinframe->base = NULL;
3429         skinframe->pants = NULL;
3430         skinframe->shirt = NULL;
3431         skinframe->nmap = NULL;
3432         skinframe->gloss = NULL;
3433         skinframe->glow = NULL;
3434         skinframe->fog = NULL;
3435         skinframe->reflect = NULL;
3436         skinframe->hasalpha = false;
3437
3438         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3439         if (!skindata)
3440                 return NULL;
3441
3442         if (developer_loading.integer)
3443                 Con_Printf("loading quake skin \"%s\"\n", name);
3444
3445         // 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)
3446         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3447         memcpy(skinframe->qpixels, skindata, width*height);
3448         skinframe->qwidth = width;
3449         skinframe->qheight = height;
3450
3451         featuresmask = 0;
3452         for (i = 0;i < width * height;i++)
3453                 featuresmask |= palette_featureflags[skindata[i]];
3454
3455         skinframe->hasalpha = false;
3456         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3457         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3458         skinframe->qgeneratemerged = true;
3459         skinframe->qgeneratebase = skinframe->qhascolormapping;
3460         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3461
3462         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3463         //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]);
3464
3465         return skinframe;
3466 }
3467
3468 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3469 {
3470         int width;
3471         int height;
3472         unsigned char *skindata;
3473
3474         if (!skinframe->qpixels)
3475                 return;
3476
3477         if (!skinframe->qhascolormapping)
3478                 colormapped = false;
3479
3480         if (colormapped)
3481         {
3482                 if (!skinframe->qgeneratebase)
3483                         return;
3484         }
3485         else
3486         {
3487                 if (!skinframe->qgeneratemerged)
3488                         return;
3489         }
3490
3491         width = skinframe->qwidth;
3492         height = skinframe->qheight;
3493         skindata = skinframe->qpixels;
3494
3495         if (skinframe->qgeneratenmap)
3496         {
3497                 unsigned char *temp1, *temp2;
3498                 skinframe->qgeneratenmap = false;
3499                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3500                 temp2 = temp1 + width * height * 4;
3501                 // use either a custom palette or the quake palette
3502                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3503                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3504                 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);
3505                 Mem_Free(temp1);
3506         }
3507
3508         if (skinframe->qgenerateglow)
3509         {
3510                 skinframe->qgenerateglow = false;
3511                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3512         }
3513
3514         if (colormapped)
3515         {
3516                 skinframe->qgeneratebase = false;
3517                 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);
3518                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3519                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3520         }
3521         else
3522         {
3523                 skinframe->qgeneratemerged = false;
3524                 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);
3525         }
3526
3527         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3528         {
3529                 Mem_Free(skinframe->qpixels);
3530                 skinframe->qpixels = NULL;
3531         }
3532 }
3533
3534 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)
3535 {
3536         int i;
3537         skinframe_t *skinframe;
3538
3539         if (cls.state == ca_dedicated)
3540                 return NULL;
3541
3542         // if already loaded just return it, otherwise make a new skinframe
3543         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3544         if (skinframe && skinframe->base)
3545                 return skinframe;
3546
3547         skinframe->stain = NULL;
3548         skinframe->merged = NULL;
3549         skinframe->base = NULL;
3550         skinframe->pants = NULL;
3551         skinframe->shirt = NULL;
3552         skinframe->nmap = NULL;
3553         skinframe->gloss = NULL;
3554         skinframe->glow = NULL;
3555         skinframe->fog = NULL;
3556         skinframe->reflect = NULL;
3557         skinframe->hasalpha = false;
3558
3559         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3560         if (!skindata)
3561                 return NULL;
3562
3563         if (developer_loading.integer)
3564                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3565
3566         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3567         if (textureflags & TEXF_ALPHA)
3568         {
3569                 for (i = 0;i < width * height;i++)
3570                 {
3571                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3572                         {
3573                                 skinframe->hasalpha = true;
3574                                 break;
3575                         }
3576                 }
3577                 if (r_loadfog && skinframe->hasalpha)
3578                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3579         }
3580
3581         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3582         //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]);
3583
3584         return skinframe;
3585 }
3586
3587 skinframe_t *R_SkinFrame_LoadMissing(void)
3588 {
3589         skinframe_t *skinframe;
3590
3591         if (cls.state == ca_dedicated)
3592                 return NULL;
3593
3594         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3595         skinframe->stain = NULL;
3596         skinframe->merged = NULL;
3597         skinframe->base = NULL;
3598         skinframe->pants = NULL;
3599         skinframe->shirt = NULL;
3600         skinframe->nmap = NULL;
3601         skinframe->gloss = NULL;
3602         skinframe->glow = NULL;
3603         skinframe->fog = NULL;
3604         skinframe->reflect = NULL;
3605         skinframe->hasalpha = false;
3606
3607         skinframe->avgcolor[0] = rand() / RAND_MAX;
3608         skinframe->avgcolor[1] = rand() / RAND_MAX;
3609         skinframe->avgcolor[2] = rand() / RAND_MAX;
3610         skinframe->avgcolor[3] = 1;
3611
3612         return skinframe;
3613 }
3614
3615 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3616 typedef struct suffixinfo_s
3617 {
3618         const char *suffix;
3619         qboolean flipx, flipy, flipdiagonal;
3620 }
3621 suffixinfo_t;
3622 static suffixinfo_t suffix[3][6] =
3623 {
3624         {
3625                 {"px",   false, false, false},
3626                 {"nx",   false, false, false},
3627                 {"py",   false, false, false},
3628                 {"ny",   false, false, false},
3629                 {"pz",   false, false, false},
3630                 {"nz",   false, false, false}
3631         },
3632         {
3633                 {"posx", false, false, false},
3634                 {"negx", false, false, false},
3635                 {"posy", false, false, false},
3636                 {"negy", false, false, false},
3637                 {"posz", false, false, false},
3638                 {"negz", false, false, false}
3639         },
3640         {
3641                 {"rt",    true, false,  true},
3642                 {"lf",   false,  true,  true},
3643                 {"ft",    true,  true, false},
3644                 {"bk",   false, false, false},
3645                 {"up",    true, false,  true},
3646                 {"dn",    true, false,  true}
3647         }
3648 };
3649
3650 static int componentorder[4] = {0, 1, 2, 3};
3651
3652 rtexture_t *R_LoadCubemap(const char *basename)
3653 {
3654         int i, j, cubemapsize;
3655         unsigned char *cubemappixels, *image_buffer;
3656         rtexture_t *cubemaptexture;
3657         char name[256];
3658         // must start 0 so the first loadimagepixels has no requested width/height
3659         cubemapsize = 0;
3660         cubemappixels = NULL;
3661         cubemaptexture = NULL;
3662         // keep trying different suffix groups (posx, px, rt) until one loads
3663         for (j = 0;j < 3 && !cubemappixels;j++)
3664         {
3665                 // load the 6 images in the suffix group
3666                 for (i = 0;i < 6;i++)
3667                 {
3668                         // generate an image name based on the base and and suffix
3669                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3670                         // load it
3671                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3672                         {
3673                                 // an image loaded, make sure width and height are equal
3674                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3675                                 {
3676                                         // if this is the first image to load successfully, allocate the cubemap memory
3677                                         if (!cubemappixels && image_width >= 1)
3678                                         {
3679                                                 cubemapsize = image_width;
3680                                                 // note this clears to black, so unavailable sides are black
3681                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3682                                         }
3683                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3684                                         if (cubemappixels)
3685                                                 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);
3686                                 }
3687                                 else
3688                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3689                                 // free the image
3690                                 Mem_Free(image_buffer);
3691                         }
3692                 }
3693         }
3694         // if a cubemap loaded, upload it
3695         if (cubemappixels)
3696         {
3697                 if (developer_loading.integer)
3698                         Con_Printf("loading cubemap \"%s\"\n", basename);
3699
3700                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3701                 Mem_Free(cubemappixels);
3702         }
3703         else
3704         {
3705                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3706                 if (developer_loading.integer)
3707                 {
3708                         Con_Printf("(tried tried images ");
3709                         for (j = 0;j < 3;j++)
3710                                 for (i = 0;i < 6;i++)
3711                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3712                         Con_Print(" and was unable to find any of them).\n");
3713                 }
3714         }
3715         return cubemaptexture;
3716 }
3717
3718 rtexture_t *R_GetCubemap(const char *basename)
3719 {
3720         int i;
3721         for (i = 0;i < r_texture_numcubemaps;i++)
3722                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3723                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3724         if (i >= MAX_CUBEMAPS)
3725                 return r_texture_whitecube;
3726         r_texture_numcubemaps++;
3727         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3728         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3729         return r_texture_cubemaps[i].texture;
3730 }
3731
3732 void R_FreeCubemaps(void)
3733 {
3734         int i;
3735         for (i = 0;i < r_texture_numcubemaps;i++)
3736         {
3737                 if (developer_loading.integer)
3738                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3739                 if (r_texture_cubemaps[i].texture)
3740                         R_FreeTexture(r_texture_cubemaps[i].texture);
3741         }
3742         r_texture_numcubemaps = 0;
3743 }
3744
3745 void R_Main_FreeViewCache(void)
3746 {
3747         if (r_refdef.viewcache.entityvisible)
3748                 Mem_Free(r_refdef.viewcache.entityvisible);
3749         if (r_refdef.viewcache.world_pvsbits)
3750                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3751         if (r_refdef.viewcache.world_leafvisible)
3752                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3753         if (r_refdef.viewcache.world_surfacevisible)
3754                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3755         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3756 }
3757
3758 void R_Main_ResizeViewCache(void)
3759 {
3760         int numentities = r_refdef.scene.numentities;
3761         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3762         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3763         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3764         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3765         if (r_refdef.viewcache.maxentities < numentities)
3766         {
3767                 r_refdef.viewcache.maxentities = numentities;
3768                 if (r_refdef.viewcache.entityvisible)
3769                         Mem_Free(r_refdef.viewcache.entityvisible);
3770                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3771         }
3772         if (r_refdef.viewcache.world_numclusters != numclusters)
3773         {
3774                 r_refdef.viewcache.world_numclusters = numclusters;
3775                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3776                 if (r_refdef.viewcache.world_pvsbits)
3777                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3778                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3779         }
3780         if (r_refdef.viewcache.world_numleafs != numleafs)
3781         {
3782                 r_refdef.viewcache.world_numleafs = numleafs;
3783                 if (r_refdef.viewcache.world_leafvisible)
3784                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3785                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3786         }
3787         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3788         {
3789                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3790                 if (r_refdef.viewcache.world_surfacevisible)
3791                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3792                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3793         }
3794 }
3795
3796 extern rtexture_t *loadingscreentexture;
3797 void gl_main_start(void)
3798 {
3799         loadingscreentexture = NULL;
3800         r_texture_blanknormalmap = NULL;
3801         r_texture_white = NULL;
3802         r_texture_grey128 = NULL;
3803         r_texture_black = NULL;
3804         r_texture_whitecube = NULL;
3805         r_texture_normalizationcube = NULL;
3806         r_texture_fogattenuation = NULL;
3807         r_texture_fogheighttexture = NULL;
3808         r_texture_gammaramps = NULL;
3809         r_texture_numcubemaps = 0;
3810
3811         r_loaddds = r_texture_dds_load.integer != 0;
3812         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3813
3814         switch(vid.renderpath)
3815         {
3816         case RENDERPATH_GL20:
3817         case RENDERPATH_D3D9:
3818         case RENDERPATH_D3D10:
3819         case RENDERPATH_D3D11:
3820         case RENDERPATH_SOFT:
3821                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3822                 Cvar_SetValueQuick(&gl_combine, 1);
3823                 Cvar_SetValueQuick(&r_glsl, 1);
3824                 r_loadnormalmap = true;
3825                 r_loadgloss = true;
3826                 r_loadfog = false;
3827                 break;
3828         case RENDERPATH_GL13:
3829                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3830                 Cvar_SetValueQuick(&gl_combine, 1);
3831                 Cvar_SetValueQuick(&r_glsl, 0);
3832                 r_loadnormalmap = false;
3833                 r_loadgloss = false;
3834                 r_loadfog = true;
3835                 break;
3836         case RENDERPATH_GL11:
3837                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3838                 Cvar_SetValueQuick(&gl_combine, 0);
3839                 Cvar_SetValueQuick(&r_glsl, 0);
3840                 r_loadnormalmap = false;
3841                 r_loadgloss = false;
3842                 r_loadfog = true;
3843                 break;
3844         case RENDERPATH_GLES2:
3845                 Cvar_SetValueQuick(&r_textureunits, 1);
3846                 Cvar_SetValueQuick(&gl_combine, 1);
3847                 Cvar_SetValueQuick(&r_glsl, 1);
3848                 r_loadnormalmap = true;
3849                 r_loadgloss = false;
3850                 r_loadfog = false;
3851                 break;
3852         }
3853
3854         R_AnimCache_Free();
3855         R_FrameData_Reset();
3856
3857         r_numqueries = 0;
3858         r_maxqueries = 0;
3859         memset(r_queries, 0, sizeof(r_queries));
3860
3861         r_qwskincache = NULL;
3862         r_qwskincache_size = 0;
3863
3864         // due to caching of texture_t references, the collision cache must be reset
3865         Collision_Cache_Reset(true);
3866
3867         // set up r_skinframe loading system for textures
3868         memset(&r_skinframe, 0, sizeof(r_skinframe));
3869         r_skinframe.loadsequence = 1;
3870         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3871
3872         r_main_texturepool = R_AllocTexturePool();
3873         R_BuildBlankTextures();
3874         R_BuildNoTexture();
3875         if (vid.support.arb_texture_cube_map)
3876         {
3877                 R_BuildWhiteCube();
3878                 R_BuildNormalizationCube();
3879         }
3880         r_texture_fogattenuation = NULL;
3881         r_texture_fogheighttexture = NULL;
3882         r_texture_gammaramps = NULL;
3883         //r_texture_fogintensity = NULL;
3884         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3885         memset(&r_waterstate, 0, sizeof(r_waterstate));
3886         r_glsl_permutation = NULL;
3887         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3888         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3889         glslshaderstring = NULL;
3890 #ifdef SUPPORTD3D
3891         r_hlsl_permutation = NULL;
3892         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3893         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3894 #endif
3895         hlslshaderstring = NULL;
3896         memset(&r_svbsp, 0, sizeof (r_svbsp));
3897
3898         r_refdef.fogmasktable_density = 0;
3899 }
3900
3901 void gl_main_shutdown(void)
3902 {
3903         R_AnimCache_Free();
3904         R_FrameData_Reset();
3905
3906         R_Main_FreeViewCache();
3907
3908         switch(vid.renderpath)
3909         {
3910         case RENDERPATH_GL11:
3911         case RENDERPATH_GL13:
3912         case RENDERPATH_GL20:
3913         case RENDERPATH_GLES2:
3914                 if (r_maxqueries)
3915                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3916                 break;
3917         case RENDERPATH_D3D9:
3918                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3919                 break;
3920         case RENDERPATH_D3D10:
3921                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3922                 break;
3923         case RENDERPATH_D3D11:
3924                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3925                 break;
3926         case RENDERPATH_SOFT:
3927                 break;
3928         }
3929
3930         r_numqueries = 0;
3931         r_maxqueries = 0;
3932         memset(r_queries, 0, sizeof(r_queries));
3933
3934         r_qwskincache = NULL;
3935         r_qwskincache_size = 0;
3936
3937         // clear out the r_skinframe state
3938         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3939         memset(&r_skinframe, 0, sizeof(r_skinframe));
3940
3941         if (r_svbsp.nodes)
3942                 Mem_Free(r_svbsp.nodes);
3943         memset(&r_svbsp, 0, sizeof (r_svbsp));
3944         R_FreeTexturePool(&r_main_texturepool);
3945         loadingscreentexture = NULL;
3946         r_texture_blanknormalmap = NULL;
3947         r_texture_white = NULL;
3948         r_texture_grey128 = NULL;
3949         r_texture_black = NULL;
3950         r_texture_whitecube = NULL;
3951         r_texture_normalizationcube = NULL;
3952         r_texture_fogattenuation = NULL;
3953         r_texture_fogheighttexture = NULL;
3954         r_texture_gammaramps = NULL;
3955         r_texture_numcubemaps = 0;
3956         //r_texture_fogintensity = NULL;
3957         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3958         memset(&r_waterstate, 0, sizeof(r_waterstate));
3959         R_GLSL_Restart_f();
3960
3961         r_glsl_permutation = NULL;
3962         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3963         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3964         glslshaderstring = NULL;
3965 #ifdef SUPPORTD3D
3966         r_hlsl_permutation = NULL;
3967         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3968         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3969 #endif
3970         hlslshaderstring = NULL;
3971 }
3972
3973 extern void CL_ParseEntityLump(char *entitystring);
3974 void gl_main_newmap(void)
3975 {
3976         // FIXME: move this code to client
3977         char *entities, entname[MAX_QPATH];
3978         if (r_qwskincache)
3979                 Mem_Free(r_qwskincache);
3980         r_qwskincache = NULL;
3981         r_qwskincache_size = 0;
3982         if (cl.worldmodel)
3983         {
3984                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3985                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3986                 {
3987                         CL_ParseEntityLump(entities);
3988                         Mem_Free(entities);
3989                         return;
3990                 }
3991                 if (cl.worldmodel->brush.entities)
3992                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3993         }
3994         R_Main_FreeViewCache();
3995
3996         R_FrameData_Reset();
3997 }
3998
3999 void GL_Main_Init(void)
4000 {
4001         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4002
4003         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4004         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4005         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4006         if (gamemode == GAME_NEHAHRA)
4007         {
4008                 Cvar_RegisterVariable (&gl_fogenable);
4009                 Cvar_RegisterVariable (&gl_fogdensity);
4010                 Cvar_RegisterVariable (&gl_fogred);
4011                 Cvar_RegisterVariable (&gl_foggreen);
4012                 Cvar_RegisterVariable (&gl_fogblue);
4013                 Cvar_RegisterVariable (&gl_fogstart);
4014                 Cvar_RegisterVariable (&gl_fogend);
4015                 Cvar_RegisterVariable (&gl_skyclip);
4016         }
4017         Cvar_RegisterVariable(&r_motionblur);
4018         Cvar_RegisterVariable(&r_motionblur_maxblur);
4019         Cvar_RegisterVariable(&r_motionblur_bmin);
4020         Cvar_RegisterVariable(&r_motionblur_vmin);
4021         Cvar_RegisterVariable(&r_motionblur_vmax);
4022         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4023         Cvar_RegisterVariable(&r_motionblur_randomize);
4024         Cvar_RegisterVariable(&r_damageblur);
4025         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4026         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4027         Cvar_RegisterVariable(&r_equalize_entities_by);
4028         Cvar_RegisterVariable(&r_equalize_entities_to);
4029         Cvar_RegisterVariable(&r_depthfirst);
4030         Cvar_RegisterVariable(&r_useinfinitefarclip);
4031         Cvar_RegisterVariable(&r_farclip_base);
4032         Cvar_RegisterVariable(&r_farclip_world);
4033         Cvar_RegisterVariable(&r_nearclip);
4034         Cvar_RegisterVariable(&r_showbboxes);
4035         Cvar_RegisterVariable(&r_showsurfaces);
4036         Cvar_RegisterVariable(&r_showtris);
4037         Cvar_RegisterVariable(&r_shownormals);
4038         Cvar_RegisterVariable(&r_showlighting);
4039         Cvar_RegisterVariable(&r_showshadowvolumes);
4040         Cvar_RegisterVariable(&r_showcollisionbrushes);
4041         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4042         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4043         Cvar_RegisterVariable(&r_showdisabledepthtest);
4044         Cvar_RegisterVariable(&r_drawportals);
4045         Cvar_RegisterVariable(&r_drawentities);
4046         Cvar_RegisterVariable(&r_draw2d);
4047         Cvar_RegisterVariable(&r_drawworld);
4048         Cvar_RegisterVariable(&r_cullentities_trace);
4049         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4050         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4051         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4052         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4053         Cvar_RegisterVariable(&r_drawviewmodel);
4054         Cvar_RegisterVariable(&r_drawexteriormodel);
4055         Cvar_RegisterVariable(&r_speeds);
4056         Cvar_RegisterVariable(&r_fullbrights);
4057         Cvar_RegisterVariable(&r_wateralpha);
4058         Cvar_RegisterVariable(&r_dynamic);
4059         Cvar_RegisterVariable(&r_fakelight);
4060         Cvar_RegisterVariable(&r_fakelight_intensity);
4061         Cvar_RegisterVariable(&r_fullbright);
4062         Cvar_RegisterVariable(&r_shadows);
4063         Cvar_RegisterVariable(&r_shadows_darken);
4064         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4065         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4066         Cvar_RegisterVariable(&r_shadows_throwdistance);
4067         Cvar_RegisterVariable(&r_shadows_throwdirection);
4068         Cvar_RegisterVariable(&r_shadows_focus);
4069         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4070         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4071         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4072         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4073         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4074         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4075         Cvar_RegisterVariable(&r_fog_exp2);
4076         Cvar_RegisterVariable(&r_fog_clear);
4077         Cvar_RegisterVariable(&r_drawfog);
4078         Cvar_RegisterVariable(&r_transparentdepthmasking);
4079         Cvar_RegisterVariable(&r_texture_dds_load);
4080         Cvar_RegisterVariable(&r_texture_dds_save);
4081         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4082         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4083         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4084         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4085         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4086         Cvar_RegisterVariable(&r_textureunits);
4087         Cvar_RegisterVariable(&gl_combine);
4088         Cvar_RegisterVariable(&r_glsl);
4089         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4090         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4091         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4092         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4093         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4094         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4095         Cvar_RegisterVariable(&r_glsl_postprocess);
4096         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4097         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4098         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4099         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4100         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4101         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4102         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4103         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4104
4105         Cvar_RegisterVariable(&r_water);
4106         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4107         Cvar_RegisterVariable(&r_water_clippingplanebias);
4108         Cvar_RegisterVariable(&r_water_refractdistort);
4109         Cvar_RegisterVariable(&r_water_reflectdistort);
4110         Cvar_RegisterVariable(&r_water_scissormode);
4111         Cvar_RegisterVariable(&r_lerpsprites);
4112         Cvar_RegisterVariable(&r_lerpmodels);
4113         Cvar_RegisterVariable(&r_lerplightstyles);
4114         Cvar_RegisterVariable(&r_waterscroll);
4115         Cvar_RegisterVariable(&r_bloom);
4116         Cvar_RegisterVariable(&r_bloom_colorscale);
4117         Cvar_RegisterVariable(&r_bloom_brighten);
4118         Cvar_RegisterVariable(&r_bloom_blur);
4119         Cvar_RegisterVariable(&r_bloom_resolution);
4120         Cvar_RegisterVariable(&r_bloom_colorexponent);
4121         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4122         Cvar_RegisterVariable(&r_hdr);
4123         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4124         Cvar_RegisterVariable(&r_hdr_glowintensity);
4125         Cvar_RegisterVariable(&r_hdr_range);
4126         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4127         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4128         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4129         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4130         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4131         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4132         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4133         Cvar_RegisterVariable(&developer_texturelogging);
4134         Cvar_RegisterVariable(&gl_lightmaps);
4135         Cvar_RegisterVariable(&r_test);
4136         Cvar_RegisterVariable(&r_glsl_saturation);
4137         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
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_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, 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                         case RENDERPATH_SOFT:
4903                                 // non-flipped y coordinates
4904                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4905                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4906                                 break;
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         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9203         {
9204                 f = 1 - RSurf_FogVertex(v);
9205                 c[0] = r;
9206                 c[1] = g;
9207                 c[2] = b;
9208                 c[3] = f * a;
9209         }
9210 }
9211
9212 void RSurf_SetupDepthAndCulling(void)
9213 {
9214         // submodels are biased to avoid z-fighting with world surfaces that they
9215         // may be exactly overlapping (avoids z-fighting artifacts on certain
9216         // doors and things in Quake maps)
9217         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9218         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9219         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9220         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9221 }
9222
9223 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9224 {
9225         // transparent sky would be ridiculous
9226         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9227                 return;
9228         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9229         skyrenderlater = true;
9230         RSurf_SetupDepthAndCulling();
9231         GL_DepthMask(true);
9232         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9233         // skymasking on them, and Quake3 never did sky masking (unlike
9234         // software Quake and software Quake2), so disable the sky masking
9235         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9236         // and skymasking also looks very bad when noclipping outside the
9237         // level, so don't use it then either.
9238         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9239         {
9240                 R_Mesh_ResetTextureState();
9241                 if (skyrendermasked)
9242                 {
9243                         R_SetupShader_DepthOrShadow();
9244                         // depth-only (masking)
9245                         GL_ColorMask(0,0,0,0);
9246                         // just to make sure that braindead drivers don't draw
9247                         // anything despite that colormask...
9248                         GL_BlendFunc(GL_ZERO, GL_ONE);
9249                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9250                         if (rsurface.batchvertex3fbuffer)
9251                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9252                         else
9253                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9254                 }
9255                 else
9256                 {
9257                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9258                         // fog sky
9259                         GL_BlendFunc(GL_ONE, GL_ZERO);
9260                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9261                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9262                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9263                 }
9264                 RSurf_DrawBatch();
9265                 if (skyrendermasked)
9266                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9267         }
9268         R_Mesh_ResetTextureState();
9269         GL_Color(1, 1, 1, 1);
9270 }
9271
9272 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9273 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9274 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9275 {
9276         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9277                 return;
9278         if (prepass)
9279         {
9280                 // render screenspace normalmap to texture
9281                 GL_DepthMask(true);
9282                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9283                 RSurf_DrawBatch();
9284                 return;
9285         }
9286
9287         // bind lightmap texture
9288
9289         // water/refraction/reflection/camera surfaces have to be handled specially
9290         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9291         {
9292                 int start, end, startplaneindex;
9293                 for (start = 0;start < texturenumsurfaces;start = end)
9294                 {
9295                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9296                         if(startplaneindex < 0)
9297                         {
9298                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9299                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9300                                 end = start + 1;
9301                                 continue;
9302                         }
9303                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9304                                 ;
9305                         // now that we have a batch using the same planeindex, render it
9306                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9307                         {
9308                                 // render water or distortion background
9309                                 GL_DepthMask(true);
9310                                 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));
9311                                 RSurf_DrawBatch();
9312                                 // blend surface on top
9313                                 GL_DepthMask(false);
9314                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9315                                 RSurf_DrawBatch();
9316                         }
9317                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9318                         {
9319                                 // render surface with reflection texture as input
9320                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9321                                 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));
9322                                 RSurf_DrawBatch();
9323                         }
9324                 }
9325                 return;
9326         }
9327
9328         // render surface batch normally
9329         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9330         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9331         RSurf_DrawBatch();
9332 }
9333
9334 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9335 {
9336         // OpenGL 1.3 path - anything not completely ancient
9337         qboolean applycolor;
9338         qboolean applyfog;
9339         int layerindex;
9340         const texturelayer_t *layer;
9341         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);
9342         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9343
9344         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9345         {
9346                 vec4_t layercolor;
9347                 int layertexrgbscale;
9348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9349                 {
9350                         if (layerindex == 0)
9351                                 GL_AlphaTest(true);
9352                         else
9353                         {
9354                                 GL_AlphaTest(false);
9355                                 GL_DepthFunc(GL_EQUAL);
9356                         }
9357                 }
9358                 GL_DepthMask(layer->depthmask && writedepth);
9359                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9360                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9361                 {
9362                         layertexrgbscale = 4;
9363                         VectorScale(layer->color, 0.25f, layercolor);
9364                 }
9365                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9366                 {
9367                         layertexrgbscale = 2;
9368                         VectorScale(layer->color, 0.5f, layercolor);
9369                 }
9370                 else
9371                 {
9372                         layertexrgbscale = 1;
9373                         VectorScale(layer->color, 1.0f, layercolor);
9374                 }
9375                 layercolor[3] = layer->color[3];
9376                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9377                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9378                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9379                 switch (layer->type)
9380                 {
9381                 case TEXTURELAYERTYPE_LITTEXTURE:
9382                         // single-pass lightmapped texture with 2x rgbscale
9383                         R_Mesh_TexBind(0, r_texture_white);
9384                         R_Mesh_TexMatrix(0, NULL);
9385                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9386                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9387                         R_Mesh_TexBind(1, layer->texture);
9388                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9389                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9390                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9391                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9392                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9393                         else if (FAKELIGHT_ENABLED)
9394                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9395                         else if (rsurface.uselightmaptexture)
9396                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9397                         else
9398                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9399                         break;
9400                 case TEXTURELAYERTYPE_TEXTURE:
9401                         // singletexture unlit texture with transparency support
9402                         R_Mesh_TexBind(0, layer->texture);
9403                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9404                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9405                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9406                         R_Mesh_TexBind(1, 0);
9407                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9408                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9409                         break;
9410                 case TEXTURELAYERTYPE_FOG:
9411                         // singletexture fogging
9412                         if (layer->texture)
9413                         {
9414                                 R_Mesh_TexBind(0, layer->texture);
9415                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9416                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9417                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9418                         }
9419                         else
9420                         {
9421                                 R_Mesh_TexBind(0, 0);
9422                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9423                         }
9424                         R_Mesh_TexBind(1, 0);
9425                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9426                         // generate a color array for the fog pass
9427                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9428                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9429                         RSurf_DrawBatch();
9430                         break;
9431                 default:
9432                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9433                 }
9434         }
9435         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9436         {
9437                 GL_DepthFunc(GL_LEQUAL);
9438                 GL_AlphaTest(false);
9439         }
9440 }
9441
9442 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9443 {
9444         // OpenGL 1.1 - crusty old voodoo path
9445         qboolean applyfog;
9446         int layerindex;
9447         const texturelayer_t *layer;
9448         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);
9449         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9450
9451         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9452         {
9453                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9454                 {
9455                         if (layerindex == 0)
9456                                 GL_AlphaTest(true);
9457                         else
9458                         {
9459                                 GL_AlphaTest(false);
9460                                 GL_DepthFunc(GL_EQUAL);
9461                         }
9462                 }
9463                 GL_DepthMask(layer->depthmask && writedepth);
9464                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9465                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9466                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9467                 switch (layer->type)
9468                 {
9469                 case TEXTURELAYERTYPE_LITTEXTURE:
9470                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9471                         {
9472                                 // two-pass lit texture with 2x rgbscale
9473                                 // first the lightmap pass
9474                                 R_Mesh_TexBind(0, r_texture_white);
9475                                 R_Mesh_TexMatrix(0, NULL);
9476                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9477                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9478                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9479                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9480                                 else if (FAKELIGHT_ENABLED)
9481                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9482                                 else if (rsurface.uselightmaptexture)
9483                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9484                                 else
9485                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9486                                 // then apply the texture to it
9487                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9488                                 R_Mesh_TexBind(0, layer->texture);
9489                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9490                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9491                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9492                                 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);
9493                         }
9494                         else
9495                         {
9496                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9497                                 R_Mesh_TexBind(0, layer->texture);
9498                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9499                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9500                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9501                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9502                                         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);
9503                                 else
9504                                         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);
9505                         }
9506                         break;
9507                 case TEXTURELAYERTYPE_TEXTURE:
9508                         // singletexture unlit texture with transparency support
9509                         R_Mesh_TexBind(0, layer->texture);
9510                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9511                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9512                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9513                         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);
9514                         break;
9515                 case TEXTURELAYERTYPE_FOG:
9516                         // singletexture fogging
9517                         if (layer->texture)
9518                         {
9519                                 R_Mesh_TexBind(0, layer->texture);
9520                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9521                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9522                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9523                         }
9524                         else
9525                         {
9526                                 R_Mesh_TexBind(0, 0);
9527                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9528                         }
9529                         // generate a color array for the fog pass
9530                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9531                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9532                         RSurf_DrawBatch();
9533                         break;
9534                 default:
9535                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9536                 }
9537         }
9538         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9539         {
9540                 GL_DepthFunc(GL_LEQUAL);
9541                 GL_AlphaTest(false);
9542         }
9543 }
9544
9545 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9546 {
9547         int vi;
9548         int j;
9549         r_vertexgeneric_t *batchvertex;
9550         float c[4];
9551
9552 //      R_Mesh_ResetTextureState();
9553         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9554
9555         if(rsurface.texture && rsurface.texture->currentskinframe)
9556         {
9557                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9558                 c[3] *= rsurface.texture->currentalpha;
9559         }
9560         else
9561         {
9562                 c[0] = 1;
9563                 c[1] = 0;
9564                 c[2] = 1;
9565                 c[3] = 1;
9566         }
9567
9568         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9569         {
9570                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9571                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9572                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9573         }
9574
9575         // brighten it up (as texture value 127 means "unlit")
9576         c[0] *= 2 * r_refdef.view.colorscale;
9577         c[1] *= 2 * r_refdef.view.colorscale;
9578         c[2] *= 2 * r_refdef.view.colorscale;
9579
9580         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9581                 c[3] *= r_wateralpha.value;
9582
9583         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9584         {
9585                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9586                 GL_DepthMask(false);
9587         }
9588         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9589         {
9590                 GL_BlendFunc(GL_ONE, GL_ONE);
9591                 GL_DepthMask(false);
9592         }
9593         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9594         {
9595                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9596                 GL_DepthMask(false);
9597         }
9598         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9599         {
9600                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9601                 GL_DepthMask(false);
9602         }
9603         else
9604         {
9605                 GL_BlendFunc(GL_ONE, GL_ZERO);
9606                 GL_DepthMask(writedepth);
9607         }
9608
9609         if (r_showsurfaces.integer == 3)
9610         {
9611                 rsurface.passcolor4f = NULL;
9612
9613                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9614                 {
9615                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9616
9617                         rsurface.passcolor4f = NULL;
9618                         rsurface.passcolor4f_vertexbuffer = 0;
9619                         rsurface.passcolor4f_bufferoffset = 0;
9620                 }
9621                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9622                 {
9623                         qboolean applycolor = true;
9624                         float one = 1.0;
9625
9626                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9627
9628                         r_refdef.lightmapintensity = 1;
9629                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9630                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9631                 }
9632                 else if (FAKELIGHT_ENABLED)
9633                 {
9634                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9635
9636                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9637                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9638                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9639                 }
9640                 else
9641                 {
9642                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9643
9644                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9645                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9646                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9647                 }
9648
9649                 if(!rsurface.passcolor4f)
9650                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9651
9652                 RSurf_DrawBatch_GL11_ApplyAmbient();
9653                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9654                 if(r_refdef.fogenabled)
9655                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9656                 RSurf_DrawBatch_GL11_ClampColor();
9657
9658                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9659                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9660                 RSurf_DrawBatch();
9661         }
9662         else if (!r_refdef.view.showdebug)
9663         {
9664                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9665                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9666                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9667                 {
9668                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9669                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9670                 }
9671                 R_Mesh_PrepareVertices_Generic_Unlock();
9672                 RSurf_DrawBatch();
9673         }
9674         else if (r_showsurfaces.integer == 4)
9675         {
9676                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9677                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9678                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9679                 {
9680                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9681                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9682                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9683                 }
9684                 R_Mesh_PrepareVertices_Generic_Unlock();
9685                 RSurf_DrawBatch();
9686         }
9687         else if (r_showsurfaces.integer == 2)
9688         {
9689                 const int *e;
9690                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9691                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9692                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9693                 {
9694                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9695                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9696                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9697                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9698                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9699                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9700                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9701                 }
9702                 R_Mesh_PrepareVertices_Generic_Unlock();
9703                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9704         }
9705         else
9706         {
9707                 int texturesurfaceindex;
9708                 int k;
9709                 const msurface_t *surface;
9710                 float surfacecolor4f[4];
9711                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9712                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9713                 vi = 0;
9714                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9715                 {
9716                         surface = texturesurfacelist[texturesurfaceindex];
9717                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9718                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9719                         for (j = 0;j < surface->num_vertices;j++)
9720                         {
9721                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9722                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9723                                 vi++;
9724                         }
9725                 }
9726                 R_Mesh_PrepareVertices_Generic_Unlock();
9727                 RSurf_DrawBatch();
9728         }
9729 }
9730
9731 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9732 {
9733         CHECKGLERROR
9734         RSurf_SetupDepthAndCulling();
9735         if (r_showsurfaces.integer)
9736         {
9737                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9738                 return;
9739         }
9740         switch (vid.renderpath)
9741         {
9742         case RENDERPATH_GL20:
9743         case RENDERPATH_D3D9:
9744         case RENDERPATH_D3D10:
9745         case RENDERPATH_D3D11:
9746         case RENDERPATH_SOFT:
9747         case RENDERPATH_GLES2:
9748                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9749                 break;
9750         case RENDERPATH_GL13:
9751                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9752                 break;
9753         case RENDERPATH_GL11:
9754                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9755                 break;
9756         }
9757         CHECKGLERROR
9758 }
9759
9760 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9761 {
9762         CHECKGLERROR
9763         RSurf_SetupDepthAndCulling();
9764         if (r_showsurfaces.integer)
9765         {
9766                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9767                 return;
9768         }
9769         switch (vid.renderpath)
9770         {
9771         case RENDERPATH_GL20:
9772         case RENDERPATH_D3D9:
9773         case RENDERPATH_D3D10:
9774         case RENDERPATH_D3D11:
9775         case RENDERPATH_SOFT:
9776         case RENDERPATH_GLES2:
9777                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9778                 break;
9779         case RENDERPATH_GL13:
9780                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9781                 break;
9782         case RENDERPATH_GL11:
9783                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9784                 break;
9785         }
9786         CHECKGLERROR
9787 }
9788
9789 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9790 {
9791         int i, j;
9792         int texturenumsurfaces, endsurface;
9793         texture_t *texture;
9794         const msurface_t *surface;
9795 #define MAXBATCH_TRANSPARENTSURFACES 256
9796         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9797
9798         // if the model is static it doesn't matter what value we give for
9799         // wantnormals and wanttangents, so this logic uses only rules applicable
9800         // to a model, knowing that they are meaningless otherwise
9801         if (ent == r_refdef.scene.worldentity)
9802                 RSurf_ActiveWorldEntity();
9803         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9804                 RSurf_ActiveModelEntity(ent, false, false, false);
9805         else
9806         {
9807                 switch (vid.renderpath)
9808                 {
9809                 case RENDERPATH_GL20:
9810                 case RENDERPATH_D3D9:
9811                 case RENDERPATH_D3D10:
9812                 case RENDERPATH_D3D11:
9813                 case RENDERPATH_SOFT:
9814                 case RENDERPATH_GLES2:
9815                         RSurf_ActiveModelEntity(ent, true, true, false);
9816                         break;
9817                 case RENDERPATH_GL13:
9818                 case RENDERPATH_GL11:
9819                         RSurf_ActiveModelEntity(ent, true, false, false);
9820                         break;
9821                 }
9822         }
9823
9824         if (r_transparentdepthmasking.integer)
9825         {
9826                 qboolean setup = false;
9827                 for (i = 0;i < numsurfaces;i = j)
9828                 {
9829                         j = i + 1;
9830                         surface = rsurface.modelsurfaces + surfacelist[i];
9831                         texture = surface->texture;
9832                         rsurface.texture = R_GetCurrentTexture(texture);
9833                         rsurface.lightmaptexture = NULL;
9834                         rsurface.deluxemaptexture = NULL;
9835                         rsurface.uselightmaptexture = false;
9836                         // scan ahead until we find a different texture
9837                         endsurface = min(i + 1024, numsurfaces);
9838                         texturenumsurfaces = 0;
9839                         texturesurfacelist[texturenumsurfaces++] = surface;
9840                         for (;j < endsurface;j++)
9841                         {
9842                                 surface = rsurface.modelsurfaces + surfacelist[j];
9843                                 if (texture != surface->texture)
9844                                         break;
9845                                 texturesurfacelist[texturenumsurfaces++] = surface;
9846                         }
9847                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9848                                 continue;
9849                         // render the range of surfaces as depth
9850                         if (!setup)
9851                         {
9852                                 setup = true;
9853                                 GL_ColorMask(0,0,0,0);
9854                                 GL_Color(1,1,1,1);
9855                                 GL_DepthTest(true);
9856                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9857                                 GL_DepthMask(true);
9858 //                              R_Mesh_ResetTextureState();
9859                                 R_SetupShader_DepthOrShadow();
9860                         }
9861                         RSurf_SetupDepthAndCulling();
9862                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9863                         if (rsurface.batchvertex3fbuffer)
9864                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9865                         else
9866                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9867                         RSurf_DrawBatch();
9868                 }
9869                 if (setup)
9870                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9871         }
9872
9873         for (i = 0;i < numsurfaces;i = j)
9874         {
9875                 j = i + 1;
9876                 surface = rsurface.modelsurfaces + surfacelist[i];
9877                 texture = surface->texture;
9878                 rsurface.texture = R_GetCurrentTexture(texture);
9879                 // scan ahead until we find a different texture
9880                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9881                 texturenumsurfaces = 0;
9882                 texturesurfacelist[texturenumsurfaces++] = surface;
9883                 if(FAKELIGHT_ENABLED)
9884                 {
9885                         rsurface.lightmaptexture = NULL;
9886                         rsurface.deluxemaptexture = NULL;
9887                         rsurface.uselightmaptexture = false;
9888                         for (;j < endsurface;j++)
9889                         {
9890                                 surface = rsurface.modelsurfaces + surfacelist[j];
9891                                 if (texture != surface->texture)
9892                                         break;
9893                                 texturesurfacelist[texturenumsurfaces++] = surface;
9894                         }
9895                 }
9896                 else
9897                 {
9898                         rsurface.lightmaptexture = surface->lightmaptexture;
9899                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9900                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9901                         for (;j < endsurface;j++)
9902                         {
9903                                 surface = rsurface.modelsurfaces + surfacelist[j];
9904                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9905                                         break;
9906                                 texturesurfacelist[texturenumsurfaces++] = surface;
9907                         }
9908                 }
9909                 // render the range of surfaces
9910                 if (ent == r_refdef.scene.worldentity)
9911                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9912                 else
9913                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9914         }
9915         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9916 }
9917
9918 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9919 {
9920         // transparent surfaces get pushed off into the transparent queue
9921         int surfacelistindex;
9922         const msurface_t *surface;
9923         vec3_t tempcenter, center;
9924         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9925         {
9926                 surface = texturesurfacelist[surfacelistindex];
9927                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9928                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9929                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9930                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9931                 if (queueentity->transparent_offset) // transparent offset
9932                 {
9933                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9934                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9935                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9936                 }
9937                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9938         }
9939 }
9940
9941 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9942 {
9943         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9944                 return;
9945         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9946                 return;
9947         RSurf_SetupDepthAndCulling();
9948         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9949         if (rsurface.batchvertex3fbuffer)
9950                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9951         else
9952                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9953         RSurf_DrawBatch();
9954 }
9955
9956 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9957 {
9958         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9959         CHECKGLERROR
9960         if (depthonly)
9961                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9962         else if (prepass)
9963         {
9964                 if (!rsurface.texture->currentnumlayers)
9965                         return;
9966                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9967                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9968                 else
9969                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9970         }
9971         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9972                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9973         else if (!rsurface.texture->currentnumlayers)
9974                 return;
9975         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9976         {
9977                 // in the deferred case, transparent surfaces were queued during prepass
9978                 if (!r_shadow_usingdeferredprepass)
9979                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9980         }
9981         else
9982         {
9983                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9984                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9985         }
9986         CHECKGLERROR
9987 }
9988
9989 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9990 {
9991         int i, j;
9992         texture_t *texture;
9993         R_FrameData_SetMark();
9994         // break the surface list down into batches by texture and use of lightmapping
9995         for (i = 0;i < numsurfaces;i = j)
9996         {
9997                 j = i + 1;
9998                 // texture is the base texture pointer, rsurface.texture is the
9999                 // current frame/skin the texture is directing us to use (for example
10000                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10001                 // use skin 1 instead)
10002                 texture = surfacelist[i]->texture;
10003                 rsurface.texture = R_GetCurrentTexture(texture);
10004                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10005                 {
10006                         // if this texture is not the kind we want, skip ahead to the next one
10007                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10008                                 ;
10009                         continue;
10010                 }
10011                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10012                 {
10013                         rsurface.lightmaptexture = NULL;
10014                         rsurface.deluxemaptexture = NULL;
10015                         rsurface.uselightmaptexture = false;
10016                         // simply scan ahead until we find a different texture or lightmap state
10017                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10018                                 ;
10019                 }
10020                 else
10021                 {
10022                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10023                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10024                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10025                         // simply scan ahead until we find a different texture or lightmap state
10026                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10027                                 ;
10028                 }
10029                 // render the range of surfaces
10030                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10031         }
10032         R_FrameData_ReturnToMark();
10033 }
10034
10035 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10036 {
10037         CHECKGLERROR
10038         if (depthonly)
10039                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10040         else if (prepass)
10041         {
10042                 if (!rsurface.texture->currentnumlayers)
10043                         return;
10044                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10045                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10046                 else
10047                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10048         }
10049         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10050                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10051         else if (!rsurface.texture->currentnumlayers)
10052                 return;
10053         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10054         {
10055                 // in the deferred case, transparent surfaces were queued during prepass
10056                 if (!r_shadow_usingdeferredprepass)
10057                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10058         }
10059         else
10060         {
10061                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10062                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10063         }
10064         CHECKGLERROR
10065 }
10066
10067 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10068 {
10069         int i, j;
10070         texture_t *texture;
10071         R_FrameData_SetMark();
10072         // break the surface list down into batches by texture and use of lightmapping
10073         for (i = 0;i < numsurfaces;i = j)
10074         {
10075                 j = i + 1;
10076                 // texture is the base texture pointer, rsurface.texture is the
10077                 // current frame/skin the texture is directing us to use (for example
10078                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10079                 // use skin 1 instead)
10080                 texture = surfacelist[i]->texture;
10081                 rsurface.texture = R_GetCurrentTexture(texture);
10082                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10083                 {
10084                         // if this texture is not the kind we want, skip ahead to the next one
10085                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10086                                 ;
10087                         continue;
10088                 }
10089                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10090                 {
10091                         rsurface.lightmaptexture = NULL;
10092                         rsurface.deluxemaptexture = NULL;
10093                         rsurface.uselightmaptexture = false;
10094                         // simply scan ahead until we find a different texture or lightmap state
10095                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10096                                 ;
10097                 }
10098                 else
10099                 {
10100                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10101                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10102                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10103                         // simply scan ahead until we find a different texture or lightmap state
10104                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10105                                 ;
10106                 }
10107                 // render the range of surfaces
10108                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10109         }
10110         R_FrameData_ReturnToMark();
10111 }
10112
10113 float locboxvertex3f[6*4*3] =
10114 {
10115         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10116         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10117         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10118         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10119         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10120         1,0,0, 0,0,0, 0,1,0, 1,1,0
10121 };
10122
10123 unsigned short locboxelements[6*2*3] =
10124 {
10125          0, 1, 2, 0, 2, 3,
10126          4, 5, 6, 4, 6, 7,
10127          8, 9,10, 8,10,11,
10128         12,13,14, 12,14,15,
10129         16,17,18, 16,18,19,
10130         20,21,22, 20,22,23
10131 };
10132
10133 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10134 {
10135         int i, j;
10136         cl_locnode_t *loc = (cl_locnode_t *)ent;
10137         vec3_t mins, size;
10138         float vertex3f[6*4*3];
10139         CHECKGLERROR
10140         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10141         GL_DepthMask(false);
10142         GL_DepthRange(0, 1);
10143         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10144         GL_DepthTest(true);
10145         GL_CullFace(GL_NONE);
10146         R_EntityMatrix(&identitymatrix);
10147
10148 //      R_Mesh_ResetTextureState();
10149
10150         i = surfacelist[0];
10151         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10152                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10153                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10154                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10155
10156         if (VectorCompare(loc->mins, loc->maxs))
10157         {
10158                 VectorSet(size, 2, 2, 2);
10159                 VectorMA(loc->mins, -0.5f, size, mins);
10160         }
10161         else
10162         {
10163                 VectorCopy(loc->mins, mins);
10164                 VectorSubtract(loc->maxs, loc->mins, size);
10165         }
10166
10167         for (i = 0;i < 6*4*3;)
10168                 for (j = 0;j < 3;j++, i++)
10169                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10170
10171         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10172         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10173         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10174 }
10175
10176 void R_DrawLocs(void)
10177 {
10178         int index;
10179         cl_locnode_t *loc, *nearestloc;
10180         vec3_t center;
10181         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10182         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10183         {
10184                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10185                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10186         }
10187 }
10188
10189 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10190 {
10191         if (decalsystem->decals)
10192                 Mem_Free(decalsystem->decals);
10193         memset(decalsystem, 0, sizeof(*decalsystem));
10194 }
10195
10196 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)
10197 {
10198         tridecal_t *decal;
10199         tridecal_t *decals;
10200         int i;
10201
10202         // expand or initialize the system
10203         if (decalsystem->maxdecals <= decalsystem->numdecals)
10204         {
10205                 decalsystem_t old = *decalsystem;
10206                 qboolean useshortelements;
10207                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10208                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10209                 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)));
10210                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10211                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10212                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10213                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10214                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10215                 if (decalsystem->numdecals)
10216                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10217                 if (old.decals)
10218                         Mem_Free(old.decals);
10219                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10220                         decalsystem->element3i[i] = i;
10221                 if (useshortelements)
10222                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10223                                 decalsystem->element3s[i] = i;
10224         }
10225
10226         // grab a decal and search for another free slot for the next one
10227         decals = decalsystem->decals;
10228         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10229         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10230                 ;
10231         decalsystem->freedecal = i;
10232         if (decalsystem->numdecals <= i)
10233                 decalsystem->numdecals = i + 1;
10234
10235         // initialize the decal
10236         decal->lived = 0;
10237         decal->triangleindex = triangleindex;
10238         decal->surfaceindex = surfaceindex;
10239         decal->decalsequence = decalsequence;
10240         decal->color4f[0][0] = c0[0];
10241         decal->color4f[0][1] = c0[1];
10242         decal->color4f[0][2] = c0[2];
10243         decal->color4f[0][3] = 1;
10244         decal->color4f[1][0] = c1[0];
10245         decal->color4f[1][1] = c1[1];
10246         decal->color4f[1][2] = c1[2];
10247         decal->color4f[1][3] = 1;
10248         decal->color4f[2][0] = c2[0];
10249         decal->color4f[2][1] = c2[1];
10250         decal->color4f[2][2] = c2[2];
10251         decal->color4f[2][3] = 1;
10252         decal->vertex3f[0][0] = v0[0];
10253         decal->vertex3f[0][1] = v0[1];
10254         decal->vertex3f[0][2] = v0[2];
10255         decal->vertex3f[1][0] = v1[0];
10256         decal->vertex3f[1][1] = v1[1];
10257         decal->vertex3f[1][2] = v1[2];
10258         decal->vertex3f[2][0] = v2[0];
10259         decal->vertex3f[2][1] = v2[1];
10260         decal->vertex3f[2][2] = v2[2];
10261         decal->texcoord2f[0][0] = t0[0];
10262         decal->texcoord2f[0][1] = t0[1];
10263         decal->texcoord2f[1][0] = t1[0];
10264         decal->texcoord2f[1][1] = t1[1];
10265         decal->texcoord2f[2][0] = t2[0];
10266         decal->texcoord2f[2][1] = t2[1];
10267 }
10268
10269 extern cvar_t cl_decals_bias;
10270 extern cvar_t cl_decals_models;
10271 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10272 // baseparms, parms, temps
10273 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)
10274 {
10275         int cornerindex;
10276         int index;
10277         float v[9][3];
10278         const float *vertex3f;
10279         const float *normal3f;
10280         int numpoints;
10281         float points[2][9][3];
10282         float temp[3];
10283         float tc[9][2];
10284         float f;
10285         float c[9][4];
10286         const int *e;
10287
10288         e = rsurface.modelelement3i + 3*triangleindex;
10289
10290         vertex3f = rsurface.modelvertex3f;
10291         normal3f = rsurface.modelnormal3f;
10292
10293         if (normal3f)
10294         {
10295                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10296                 {
10297                         index = 3*e[cornerindex];
10298                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10299                 }
10300         }
10301         else
10302         {
10303                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10304                 {
10305                         index = 3*e[cornerindex];
10306                         VectorCopy(vertex3f + index, v[cornerindex]);
10307                 }
10308         }
10309
10310         // cull backfaces
10311         //TriangleNormal(v[0], v[1], v[2], normal);
10312         //if (DotProduct(normal, localnormal) < 0.0f)
10313         //      continue;
10314         // clip by each of the box planes formed from the projection matrix
10315         // if anything survives, we emit the decal
10316         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]);
10317         if (numpoints < 3)
10318                 return;
10319         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]);
10320         if (numpoints < 3)
10321                 return;
10322         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]);
10323         if (numpoints < 3)
10324                 return;
10325         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]);
10326         if (numpoints < 3)
10327                 return;
10328         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]);
10329         if (numpoints < 3)
10330                 return;
10331         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]);
10332         if (numpoints < 3)
10333                 return;
10334         // some part of the triangle survived, so we have to accept it...
10335         if (dynamic)
10336         {
10337                 // dynamic always uses the original triangle
10338                 numpoints = 3;
10339                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10340                 {
10341                         index = 3*e[cornerindex];
10342                         VectorCopy(vertex3f + index, v[cornerindex]);
10343                 }
10344         }
10345         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10346         {
10347                 // convert vertex positions to texcoords
10348                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10349                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10350                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10351                 // calculate distance fade from the projection origin
10352                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10353                 f = bound(0.0f, f, 1.0f);
10354                 c[cornerindex][0] = r * f;
10355                 c[cornerindex][1] = g * f;
10356                 c[cornerindex][2] = b * f;
10357                 c[cornerindex][3] = 1.0f;
10358                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10359         }
10360         if (dynamic)
10361                 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);
10362         else
10363                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10364                         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);
10365 }
10366 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)
10367 {
10368         matrix4x4_t projection;
10369         decalsystem_t *decalsystem;
10370         qboolean dynamic;
10371         dp_model_t *model;
10372         const msurface_t *surface;
10373         const msurface_t *surfaces;
10374         const int *surfacelist;
10375         const texture_t *texture;
10376         int numtriangles;
10377         int numsurfacelist;
10378         int surfacelistindex;
10379         int surfaceindex;
10380         int triangleindex;
10381         float localorigin[3];
10382         float localnormal[3];
10383         float localmins[3];
10384         float localmaxs[3];
10385         float localsize;
10386         //float normal[3];
10387         float planes[6][4];
10388         float angles[3];
10389         bih_t *bih;
10390         int bih_triangles_count;
10391         int bih_triangles[256];
10392         int bih_surfaces[256];
10393
10394         decalsystem = &ent->decalsystem;
10395         model = ent->model;
10396         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10397         {
10398                 R_DecalSystem_Reset(&ent->decalsystem);
10399                 return;
10400         }
10401
10402         if (!model->brush.data_leafs && !cl_decals_models.integer)
10403         {
10404                 if (decalsystem->model)
10405                         R_DecalSystem_Reset(decalsystem);
10406                 return;
10407         }
10408
10409         if (decalsystem->model != model)
10410                 R_DecalSystem_Reset(decalsystem);
10411         decalsystem->model = model;
10412
10413         RSurf_ActiveModelEntity(ent, true, false, false);
10414
10415         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10416         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10417         VectorNormalize(localnormal);
10418         localsize = worldsize*rsurface.inversematrixscale;
10419         localmins[0] = localorigin[0] - localsize;
10420         localmins[1] = localorigin[1] - localsize;
10421         localmins[2] = localorigin[2] - localsize;
10422         localmaxs[0] = localorigin[0] + localsize;
10423         localmaxs[1] = localorigin[1] + localsize;
10424         localmaxs[2] = localorigin[2] + localsize;
10425
10426         //VectorCopy(localnormal, planes[4]);
10427         //VectorVectors(planes[4], planes[2], planes[0]);
10428         AnglesFromVectors(angles, localnormal, NULL, false);
10429         AngleVectors(angles, planes[0], planes[2], planes[4]);
10430         VectorNegate(planes[0], planes[1]);
10431         VectorNegate(planes[2], planes[3]);
10432         VectorNegate(planes[4], planes[5]);
10433         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10434         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10435         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10436         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10437         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10438         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10439
10440 #if 1
10441 // works
10442 {
10443         matrix4x4_t forwardprojection;
10444         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10445         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10446 }
10447 #else
10448 // broken
10449 {
10450         float projectionvector[4][3];
10451         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10452         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10453         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10454         projectionvector[0][0] = planes[0][0] * ilocalsize;
10455         projectionvector[0][1] = planes[1][0] * ilocalsize;
10456         projectionvector[0][2] = planes[2][0] * ilocalsize;
10457         projectionvector[1][0] = planes[0][1] * ilocalsize;
10458         projectionvector[1][1] = planes[1][1] * ilocalsize;
10459         projectionvector[1][2] = planes[2][1] * ilocalsize;
10460         projectionvector[2][0] = planes[0][2] * ilocalsize;
10461         projectionvector[2][1] = planes[1][2] * ilocalsize;
10462         projectionvector[2][2] = planes[2][2] * ilocalsize;
10463         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10464         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10465         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10466         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10467 }
10468 #endif
10469
10470         dynamic = model->surfmesh.isanimated;
10471         numsurfacelist = model->nummodelsurfaces;
10472         surfacelist = model->sortedmodelsurfaces;
10473         surfaces = model->data_surfaces;
10474
10475         bih = NULL;
10476         bih_triangles_count = -1;
10477         if(!dynamic)
10478         {
10479                 if(model->render_bih.numleafs)
10480                         bih = &model->render_bih;
10481                 else if(model->collision_bih.numleafs)
10482                         bih = &model->collision_bih;
10483         }
10484         if(bih)
10485                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10486         if(bih_triangles_count == 0)
10487                 return;
10488         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10489                 return;
10490         if(bih_triangles_count > 0)
10491         {
10492                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10493                 {
10494                         surfaceindex = bih_surfaces[triangleindex];
10495                         surface = surfaces + surfaceindex;
10496                         texture = surface->texture;
10497                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10498                                 continue;
10499                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10500                                 continue;
10501                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10502                 }
10503         }
10504         else
10505         {
10506                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10507                 {
10508                         surfaceindex = surfacelist[surfacelistindex];
10509                         surface = surfaces + surfaceindex;
10510                         // check cull box first because it rejects more than any other check
10511                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10512                                 continue;
10513                         // skip transparent surfaces
10514                         texture = surface->texture;
10515                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10516                                 continue;
10517                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10518                                 continue;
10519                         numtriangles = surface->num_triangles;
10520                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10521                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10522                 }
10523         }
10524 }
10525
10526 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10527 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)
10528 {
10529         int renderentityindex;
10530         float worldmins[3];
10531         float worldmaxs[3];
10532         entity_render_t *ent;
10533
10534         if (!cl_decals_newsystem.integer)
10535                 return;
10536
10537         worldmins[0] = worldorigin[0] - worldsize;
10538         worldmins[1] = worldorigin[1] - worldsize;
10539         worldmins[2] = worldorigin[2] - worldsize;
10540         worldmaxs[0] = worldorigin[0] + worldsize;
10541         worldmaxs[1] = worldorigin[1] + worldsize;
10542         worldmaxs[2] = worldorigin[2] + worldsize;
10543
10544         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10545
10546         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10547         {
10548                 ent = r_refdef.scene.entities[renderentityindex];
10549                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10550                         continue;
10551
10552                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10553         }
10554 }
10555
10556 typedef struct r_decalsystem_splatqueue_s
10557 {
10558         vec3_t worldorigin;
10559         vec3_t worldnormal;
10560         float color[4];
10561         float tcrange[4];
10562         float worldsize;
10563         int decalsequence;
10564 }
10565 r_decalsystem_splatqueue_t;
10566
10567 int r_decalsystem_numqueued = 0;
10568 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10569
10570 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)
10571 {
10572         r_decalsystem_splatqueue_t *queue;
10573
10574         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10575                 return;
10576
10577         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10578         VectorCopy(worldorigin, queue->worldorigin);
10579         VectorCopy(worldnormal, queue->worldnormal);
10580         Vector4Set(queue->color, r, g, b, a);
10581         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10582         queue->worldsize = worldsize;
10583         queue->decalsequence = cl.decalsequence++;
10584 }
10585
10586 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10587 {
10588         int i;
10589         r_decalsystem_splatqueue_t *queue;
10590
10591         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10592                 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);
10593         r_decalsystem_numqueued = 0;
10594 }
10595
10596 extern cvar_t cl_decals_max;
10597 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10598 {
10599         int i;
10600         decalsystem_t *decalsystem = &ent->decalsystem;
10601         int numdecals;
10602         int killsequence;
10603         tridecal_t *decal;
10604         float frametime;
10605         float lifetime;
10606
10607         if (!decalsystem->numdecals)
10608                 return;
10609
10610         if (r_showsurfaces.integer)
10611                 return;
10612
10613         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10614         {
10615                 R_DecalSystem_Reset(decalsystem);
10616                 return;
10617         }
10618
10619         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10620         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10621
10622         if (decalsystem->lastupdatetime)
10623                 frametime = (cl.time - decalsystem->lastupdatetime);
10624         else
10625                 frametime = 0;
10626         decalsystem->lastupdatetime = cl.time;
10627         decal = decalsystem->decals;
10628         numdecals = decalsystem->numdecals;
10629
10630         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10631         {
10632                 if (decal->color4f[0][3])
10633                 {
10634                         decal->lived += frametime;
10635                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10636                         {
10637                                 memset(decal, 0, sizeof(*decal));
10638                                 if (decalsystem->freedecal > i)
10639                                         decalsystem->freedecal = i;
10640                         }
10641                 }
10642         }
10643         decal = decalsystem->decals;
10644         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10645                 numdecals--;
10646
10647         // collapse the array by shuffling the tail decals into the gaps
10648         for (;;)
10649         {
10650                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10651                         decalsystem->freedecal++;
10652                 if (decalsystem->freedecal == numdecals)
10653                         break;
10654                 decal[decalsystem->freedecal] = decal[--numdecals];
10655         }
10656
10657         decalsystem->numdecals = numdecals;
10658
10659         if (numdecals <= 0)
10660         {
10661                 // if there are no decals left, reset decalsystem
10662                 R_DecalSystem_Reset(decalsystem);
10663         }
10664 }
10665
10666 extern skinframe_t *decalskinframe;
10667 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10668 {
10669         int i;
10670         decalsystem_t *decalsystem = &ent->decalsystem;
10671         int numdecals;
10672         tridecal_t *decal;
10673         float faderate;
10674         float alpha;
10675         float *v3f;
10676         float *c4f;
10677         float *t2f;
10678         const int *e;
10679         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10680         int numtris = 0;
10681
10682         numdecals = decalsystem->numdecals;
10683         if (!numdecals)
10684                 return;
10685
10686         if (r_showsurfaces.integer)
10687                 return;
10688
10689         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10690         {
10691                 R_DecalSystem_Reset(decalsystem);
10692                 return;
10693         }
10694
10695         // if the model is static it doesn't matter what value we give for
10696         // wantnormals and wanttangents, so this logic uses only rules applicable
10697         // to a model, knowing that they are meaningless otherwise
10698         if (ent == r_refdef.scene.worldentity)
10699                 RSurf_ActiveWorldEntity();
10700         else
10701                 RSurf_ActiveModelEntity(ent, false, false, false);
10702
10703         decalsystem->lastupdatetime = cl.time;
10704         decal = decalsystem->decals;
10705
10706         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10707
10708         // update vertex positions for animated models
10709         v3f = decalsystem->vertex3f;
10710         c4f = decalsystem->color4f;
10711         t2f = decalsystem->texcoord2f;
10712         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10713         {
10714                 if (!decal->color4f[0][3])
10715                         continue;
10716
10717                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10718                         continue;
10719
10720                 // update color values for fading decals
10721                 if (decal->lived >= cl_decals_time.value)
10722                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10723                 else
10724                         alpha = 1.0f;
10725
10726                 c4f[ 0] = decal->color4f[0][0] * alpha;
10727                 c4f[ 1] = decal->color4f[0][1] * alpha;
10728                 c4f[ 2] = decal->color4f[0][2] * alpha;
10729                 c4f[ 3] = 1;
10730                 c4f[ 4] = decal->color4f[1][0] * alpha;
10731                 c4f[ 5] = decal->color4f[1][1] * alpha;
10732                 c4f[ 6] = decal->color4f[1][2] * alpha;
10733                 c4f[ 7] = 1;
10734                 c4f[ 8] = decal->color4f[2][0] * alpha;
10735                 c4f[ 9] = decal->color4f[2][1] * alpha;
10736                 c4f[10] = decal->color4f[2][2] * alpha;
10737                 c4f[11] = 1;
10738
10739                 t2f[0] = decal->texcoord2f[0][0];
10740                 t2f[1] = decal->texcoord2f[0][1];
10741                 t2f[2] = decal->texcoord2f[1][0];
10742                 t2f[3] = decal->texcoord2f[1][1];
10743                 t2f[4] = decal->texcoord2f[2][0];
10744                 t2f[5] = decal->texcoord2f[2][1];
10745
10746                 // update vertex positions for animated models
10747                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10748                 {
10749                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10750                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10751                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10752                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10753                 }
10754                 else
10755                 {
10756                         VectorCopy(decal->vertex3f[0], v3f);
10757                         VectorCopy(decal->vertex3f[1], v3f + 3);
10758                         VectorCopy(decal->vertex3f[2], v3f + 6);
10759                 }
10760
10761                 if (r_refdef.fogenabled)
10762                 {
10763                         alpha = RSurf_FogVertex(v3f);
10764                         VectorScale(c4f, alpha, c4f);
10765                         alpha = RSurf_FogVertex(v3f + 3);
10766                         VectorScale(c4f + 4, alpha, c4f + 4);
10767                         alpha = RSurf_FogVertex(v3f + 6);
10768                         VectorScale(c4f + 8, alpha, c4f + 8);
10769                 }
10770
10771                 v3f += 9;
10772                 c4f += 12;
10773                 t2f += 6;
10774                 numtris++;
10775         }
10776
10777         if (numtris > 0)
10778         {
10779                 r_refdef.stats.drawndecals += numtris;
10780
10781                 // now render the decals all at once
10782                 // (this assumes they all use one particle font texture!)
10783                 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);
10784 //              R_Mesh_ResetTextureState();
10785                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10786                 GL_DepthMask(false);
10787                 GL_DepthRange(0, 1);
10788                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10789                 GL_DepthTest(true);
10790                 GL_CullFace(GL_NONE);
10791                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10792                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10793                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10794         }
10795 }
10796
10797 static void R_DrawModelDecals(void)
10798 {
10799         int i, numdecals;
10800
10801         // fade faster when there are too many decals
10802         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10803         for (i = 0;i < r_refdef.scene.numentities;i++)
10804                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10805
10806         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10807         for (i = 0;i < r_refdef.scene.numentities;i++)
10808                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10809                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10810
10811         R_DecalSystem_ApplySplatEntitiesQueue();
10812
10813         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10814         for (i = 0;i < r_refdef.scene.numentities;i++)
10815                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10816
10817         r_refdef.stats.totaldecals += numdecals;
10818
10819         if (r_showsurfaces.integer)
10820                 return;
10821
10822         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10823
10824         for (i = 0;i < r_refdef.scene.numentities;i++)
10825         {
10826                 if (!r_refdef.viewcache.entityvisible[i])
10827                         continue;
10828                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10829                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10830         }
10831 }
10832
10833 extern cvar_t mod_collision_bih;
10834 void R_DrawDebugModel(void)
10835 {
10836         entity_render_t *ent = rsurface.entity;
10837         int i, j, k, l, flagsmask;
10838         const msurface_t *surface;
10839         dp_model_t *model = ent->model;
10840         vec3_t v;
10841
10842         switch(vid.renderpath)
10843         {
10844         case RENDERPATH_GL11:
10845         case RENDERPATH_GL13:
10846         case RENDERPATH_GL20:
10847                 break;
10848         case RENDERPATH_D3D9:
10849                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10850                 return;
10851         case RENDERPATH_D3D10:
10852                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10853                 return;
10854         case RENDERPATH_D3D11:
10855                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10856                 return;
10857         case RENDERPATH_SOFT:
10858                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10859                 return;
10860         case RENDERPATH_GLES2:
10861                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10862                 return;
10863         }
10864
10865         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10866
10867 //      R_Mesh_ResetTextureState();
10868         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10869         GL_DepthRange(0, 1);
10870         GL_DepthTest(!r_showdisabledepthtest.integer);
10871         GL_DepthMask(false);
10872         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10873
10874         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10875         {
10876                 int triangleindex;
10877                 int bihleafindex;
10878                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10879                 const q3mbrush_t *brush;
10880                 const bih_t *bih = &model->collision_bih;
10881                 const bih_leaf_t *bihleaf;
10882                 float vertex3f[3][3];
10883                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10884                 cullbox = false;
10885                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10886                 {
10887                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10888                                 continue;
10889                         switch (bihleaf->type)
10890                         {
10891                         case BIH_BRUSH:
10892                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10893                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10894                                 {
10895                                         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);
10896                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10897                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10898                                 }
10899                                 break;
10900                         case BIH_COLLISIONTRIANGLE:
10901                                 triangleindex = bihleaf->itemindex;
10902                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10903                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10904                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10905                                 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);
10906                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10907                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10908                                 break;
10909                         case BIH_RENDERTRIANGLE:
10910                                 triangleindex = bihleaf->itemindex;
10911                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10912                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10913                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10914                                 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);
10915                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10916                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10917                                 break;
10918                         }
10919                 }
10920         }
10921
10922         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10923
10924         if (r_showtris.integer || (r_shownormals.value != 0))
10925         {
10926                 if (r_showdisabledepthtest.integer)
10927                 {
10928                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10929                         GL_DepthMask(false);
10930                 }
10931                 else
10932                 {
10933                         GL_BlendFunc(GL_ONE, GL_ZERO);
10934                         GL_DepthMask(true);
10935                 }
10936                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10937                 {
10938                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10939                                 continue;
10940                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10941                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10942                         {
10943                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10944                                 if (r_showtris.value > 0)
10945                                 {
10946                                         if (!rsurface.texture->currentlayers->depthmask)
10947                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10948                                         else if (ent == r_refdef.scene.worldentity)
10949                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10950                                         else
10951                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10952                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10953                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10954                                         RSurf_DrawBatch();
10955                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10956                                         CHECKGLERROR
10957                                 }
10958                                 if (r_shownormals.value < 0)
10959                                 {
10960                                         qglBegin(GL_LINES);
10961                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10962                                         {
10963                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10964                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10965                                                 qglVertex3f(v[0], v[1], v[2]);
10966                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10967                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10968                                                 qglVertex3f(v[0], v[1], v[2]);
10969                                         }
10970                                         qglEnd();
10971                                         CHECKGLERROR
10972                                 }
10973                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10974                                 {
10975                                         qglBegin(GL_LINES);
10976                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10977                                         {
10978                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10979                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10980                                                 qglVertex3f(v[0], v[1], v[2]);
10981                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10982                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10983                                                 qglVertex3f(v[0], v[1], v[2]);
10984                                         }
10985                                         qglEnd();
10986                                         CHECKGLERROR
10987                                         qglBegin(GL_LINES);
10988                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10989                                         {
10990                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10991                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10992                                                 qglVertex3f(v[0], v[1], v[2]);
10993                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10994                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10995                                                 qglVertex3f(v[0], v[1], v[2]);
10996                                         }
10997                                         qglEnd();
10998                                         CHECKGLERROR
10999                                         qglBegin(GL_LINES);
11000                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11001                                         {
11002                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11003                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11004                                                 qglVertex3f(v[0], v[1], v[2]);
11005                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11006                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11007                                                 qglVertex3f(v[0], v[1], v[2]);
11008                                         }
11009                                         qglEnd();
11010                                         CHECKGLERROR
11011                                 }
11012                         }
11013                 }
11014                 rsurface.texture = NULL;
11015         }
11016 }
11017
11018 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11019 int r_maxsurfacelist = 0;
11020 const msurface_t **r_surfacelist = NULL;
11021 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11022 {
11023         int i, j, endj, flagsmask;
11024         dp_model_t *model = r_refdef.scene.worldmodel;
11025         msurface_t *surfaces;
11026         unsigned char *update;
11027         int numsurfacelist = 0;
11028         if (model == NULL)
11029                 return;
11030
11031         if (r_maxsurfacelist < model->num_surfaces)
11032         {
11033                 r_maxsurfacelist = model->num_surfaces;
11034                 if (r_surfacelist)
11035                         Mem_Free((msurface_t**)r_surfacelist);
11036                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11037         }
11038
11039         RSurf_ActiveWorldEntity();
11040
11041         surfaces = model->data_surfaces;
11042         update = model->brushq1.lightmapupdateflags;
11043
11044         // update light styles on this submodel
11045         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11046         {
11047                 model_brush_lightstyleinfo_t *style;
11048                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11049                 {
11050                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11051                         {
11052                                 int *list = style->surfacelist;
11053                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11054                                 for (j = 0;j < style->numsurfaces;j++)
11055                                         update[list[j]] = true;
11056                         }
11057                 }
11058         }
11059
11060         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11061
11062         if (debug)
11063         {
11064                 R_DrawDebugModel();
11065                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11066                 return;
11067         }
11068
11069         rsurface.lightmaptexture = NULL;
11070         rsurface.deluxemaptexture = NULL;
11071         rsurface.uselightmaptexture = false;
11072         rsurface.texture = NULL;
11073         rsurface.rtlight = NULL;
11074         numsurfacelist = 0;
11075         // add visible surfaces to draw list
11076         for (i = 0;i < model->nummodelsurfaces;i++)
11077         {
11078                 j = model->sortedmodelsurfaces[i];
11079                 if (r_refdef.viewcache.world_surfacevisible[j])
11080                         r_surfacelist[numsurfacelist++] = surfaces + j;
11081         }
11082         // update lightmaps if needed
11083         if (model->brushq1.firstrender)
11084         {
11085                 model->brushq1.firstrender = false;
11086                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11087                         if (update[j])
11088                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11089         }
11090         else if (update)
11091         {
11092                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11093                         if (r_refdef.viewcache.world_surfacevisible[j])
11094                                 if (update[j])
11095                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11096         }
11097         // don't do anything if there were no surfaces
11098         if (!numsurfacelist)
11099         {
11100                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11101                 return;
11102         }
11103         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11104
11105         // add to stats if desired
11106         if (r_speeds.integer && !skysurfaces && !depthonly)
11107         {
11108                 r_refdef.stats.world_surfaces += numsurfacelist;
11109                 for (j = 0;j < numsurfacelist;j++)
11110                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11111         }
11112
11113         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11114 }
11115
11116 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11117 {
11118         int i, j, endj, flagsmask;
11119         dp_model_t *model = ent->model;
11120         msurface_t *surfaces;
11121         unsigned char *update;
11122         int numsurfacelist = 0;
11123         if (model == NULL)
11124                 return;
11125
11126         if (r_maxsurfacelist < model->num_surfaces)
11127         {
11128                 r_maxsurfacelist = model->num_surfaces;
11129                 if (r_surfacelist)
11130                         Mem_Free((msurface_t **)r_surfacelist);
11131                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11132         }
11133
11134         // if the model is static it doesn't matter what value we give for
11135         // wantnormals and wanttangents, so this logic uses only rules applicable
11136         // to a model, knowing that they are meaningless otherwise
11137         if (ent == r_refdef.scene.worldentity)
11138                 RSurf_ActiveWorldEntity();
11139         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11140                 RSurf_ActiveModelEntity(ent, false, false, false);
11141         else if (prepass)
11142                 RSurf_ActiveModelEntity(ent, true, true, true);
11143         else if (depthonly)
11144         {
11145                 switch (vid.renderpath)
11146                 {
11147                 case RENDERPATH_GL20:
11148                 case RENDERPATH_D3D9:
11149                 case RENDERPATH_D3D10:
11150                 case RENDERPATH_D3D11:
11151                 case RENDERPATH_SOFT:
11152                 case RENDERPATH_GLES2:
11153                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11154                         break;
11155                 case RENDERPATH_GL13:
11156                 case RENDERPATH_GL11:
11157                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11158                         break;
11159                 }
11160         }
11161         else
11162         {
11163                 switch (vid.renderpath)
11164                 {
11165                 case RENDERPATH_GL20:
11166                 case RENDERPATH_D3D9:
11167                 case RENDERPATH_D3D10:
11168                 case RENDERPATH_D3D11:
11169                 case RENDERPATH_SOFT:
11170                 case RENDERPATH_GLES2:
11171                         RSurf_ActiveModelEntity(ent, true, true, false);
11172                         break;
11173                 case RENDERPATH_GL13:
11174                 case RENDERPATH_GL11:
11175                         RSurf_ActiveModelEntity(ent, true, false, false);
11176                         break;
11177                 }
11178         }
11179
11180         surfaces = model->data_surfaces;
11181         update = model->brushq1.lightmapupdateflags;
11182
11183         // update light styles
11184         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11185         {
11186                 model_brush_lightstyleinfo_t *style;
11187                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11188                 {
11189                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11190                         {
11191                                 int *list = style->surfacelist;
11192                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11193                                 for (j = 0;j < style->numsurfaces;j++)
11194                                         update[list[j]] = true;
11195                         }
11196                 }
11197         }
11198
11199         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11200
11201         if (debug)
11202         {
11203                 R_DrawDebugModel();
11204                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11205                 return;
11206         }
11207
11208         rsurface.lightmaptexture = NULL;
11209         rsurface.deluxemaptexture = NULL;
11210         rsurface.uselightmaptexture = false;
11211         rsurface.texture = NULL;
11212         rsurface.rtlight = NULL;
11213         numsurfacelist = 0;
11214         // add visible surfaces to draw list
11215         for (i = 0;i < model->nummodelsurfaces;i++)
11216                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11217         // don't do anything if there were no surfaces
11218         if (!numsurfacelist)
11219         {
11220                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11221                 return;
11222         }
11223         // update lightmaps if needed
11224         if (update)
11225         {
11226                 int updated = 0;
11227                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11228                 {
11229                         if (update[j])
11230                         {
11231                                 updated++;
11232                                 R_BuildLightMap(ent, surfaces + j);
11233                         }
11234                 }
11235         }
11236         if (update)
11237                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11238                         if (update[j])
11239                                 R_BuildLightMap(ent, surfaces + j);
11240         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11241
11242         // add to stats if desired
11243         if (r_speeds.integer && !skysurfaces && !depthonly)
11244         {
11245                 r_refdef.stats.entities_surfaces += numsurfacelist;
11246                 for (j = 0;j < numsurfacelist;j++)
11247                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11248         }
11249
11250         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11251 }
11252
11253 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11254 {
11255         static texture_t texture;
11256         static msurface_t surface;
11257         const msurface_t *surfacelist = &surface;
11258
11259         // fake enough texture and surface state to render this geometry
11260
11261         texture.update_lastrenderframe = -1; // regenerate this texture
11262         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11263         texture.currentskinframe = skinframe;
11264         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11265         texture.offsetmapping = OFFSETMAPPING_OFF;
11266         texture.offsetscale = 1;
11267         texture.specularscalemod = 1;
11268         texture.specularpowermod = 1;
11269
11270         surface.texture = &texture;
11271         surface.num_triangles = numtriangles;
11272         surface.num_firsttriangle = firsttriangle;
11273         surface.num_vertices = numvertices;
11274         surface.num_firstvertex = firstvertex;
11275
11276         // now render it
11277         rsurface.texture = R_GetCurrentTexture(surface.texture);
11278         rsurface.lightmaptexture = NULL;
11279         rsurface.deluxemaptexture = NULL;
11280         rsurface.uselightmaptexture = false;
11281         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11282 }
11283
11284 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)
11285 {
11286         static msurface_t surface;
11287         const msurface_t *surfacelist = &surface;
11288
11289         // fake enough texture and surface state to render this geometry
11290         surface.texture = texture;
11291         surface.num_triangles = numtriangles;
11292         surface.num_firsttriangle = firsttriangle;
11293         surface.num_vertices = numvertices;
11294         surface.num_firstvertex = firstvertex;
11295
11296         // now render it
11297         rsurface.texture = R_GetCurrentTexture(surface.texture);
11298         rsurface.lightmaptexture = NULL;
11299         rsurface.deluxemaptexture = NULL;
11300         rsurface.uselightmaptexture = false;
11301         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11302 }