]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added r_viewscale_fpsscaling and various cvars for it, this enables
[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_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.25", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "90", "desired framerate"};
152
153 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)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 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)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 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)"};
158 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
159 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
160 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)"};
161 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)"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168
169 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)"};
170 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
171 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"};
172 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
173 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
174 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
175
176 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
177 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
178 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
179 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
180
181 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
182 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
183 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
184 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
185 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
186 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
187 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
188
189 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
190 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
191 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
192 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)"};
193 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
194 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
195 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
196 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
198 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
199
200 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"};
201
202 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"};
203
204 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
205
206 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
207 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"};
208 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
209 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
210 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
211 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
212 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)"};
213 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
214 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
215
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 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"};
218
219 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
220
221 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)"};
222
223 extern cvar_t v_glslgamma;
224
225 extern qboolean v_flipped_state;
226
227 static struct r_bloomstate_s
228 {
229         qboolean enabled;
230         qboolean hdr;
231
232         int bloomwidth, bloomheight;
233
234         textype_t texturetype;
235         int viewfbo; // used to check if r_viewfbo cvar has changed
236
237         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
240
241         int screentexturewidth, screentextureheight;
242         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
243
244         int bloomtexturewidth, bloomtextureheight;
245         rtexture_t *texture_bloom;
246
247         // arrays for rendering the screen passes
248         float screentexcoord2f[8];
249         float bloomtexcoord2f[8];
250         float offsettexcoord2f[8];
251
252         r_viewport_t viewport;
253 }
254 r_bloomstate;
255
256 r_waterstate_t r_waterstate;
257
258 /// shadow volume bsp struct with automatically growing nodes buffer
259 svbsp_t r_svbsp;
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 128; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
618 ;
619
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
622 ;
623
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
626
627 //=======================================================================================================================================================
628
629 typedef struct shaderpermutationinfo_s
630 {
631         const char *pretext;
632         const char *name;
633 }
634 shaderpermutationinfo_t;
635
636 typedef struct shadermodeinfo_s
637 {
638         const char *vertexfilename;
639         const char *geometryfilename;
640         const char *fragmentfilename;
641         const char *pretext;
642         const char *name;
643 }
644 shadermodeinfo_t;
645
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
648 {
649         {"#define USEDIFFUSE\n", " diffuse"},
650         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651         {"#define USEVIEWTINT\n", " viewtint"},
652         {"#define USECOLORMAPPING\n", " colormapping"},
653         {"#define USESATURATION\n", " saturation"},
654         {"#define USEFOGINSIDE\n", " foginside"},
655         {"#define USEFOGOUTSIDE\n", " fogoutside"},
656         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658         {"#define USEGAMMARAMPS\n", " gammaramps"},
659         {"#define USECUBEFILTER\n", " cubefilter"},
660         {"#define USEGLOW\n", " glow"},
661         {"#define USEBLOOM\n", " bloom"},
662         {"#define USESPECULAR\n", " specular"},
663         {"#define USEPOSTPROCESSING\n", " postprocessing"},
664         {"#define USEREFLECTION\n", " reflection"},
665         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674         {"#define USEALPHAKILL\n", " alphakill"},
675         {"#define USEREFLECTCUBE\n", " reflectcube"},
676         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677         {"#define USEBOUNCEGRID\n", " bouncegrid"},
678         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
679 };
680
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
700 };
701
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
703 {
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
720 };
721
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
724 {
725         /// hash lookup data
726         struct r_glsl_permutation_s *hashnext;
727         unsigned int mode;
728         unsigned int permutation;
729
730         /// indicates if we have tried compiling this permutation already
731         qboolean compiled;
732         /// 0 if compilation failed
733         int program;
734         // texture units assigned to each detected uniform
735         int tex_Texture_First;
736         int tex_Texture_Second;
737         int tex_Texture_GammaRamps;
738         int tex_Texture_Normal;
739         int tex_Texture_Color;
740         int tex_Texture_Gloss;
741         int tex_Texture_Glow;
742         int tex_Texture_SecondaryNormal;
743         int tex_Texture_SecondaryColor;
744         int tex_Texture_SecondaryGloss;
745         int tex_Texture_SecondaryGlow;
746         int tex_Texture_Pants;
747         int tex_Texture_Shirt;
748         int tex_Texture_FogHeightTexture;
749         int tex_Texture_FogMask;
750         int tex_Texture_Lightmap;
751         int tex_Texture_Deluxemap;
752         int tex_Texture_Attenuation;
753         int tex_Texture_Cube;
754         int tex_Texture_Refraction;
755         int tex_Texture_Reflection;
756         int tex_Texture_ShadowMap2D;
757         int tex_Texture_CubeProjection;
758         int tex_Texture_ScreenDepth;
759         int tex_Texture_ScreenNormalMap;
760         int tex_Texture_ScreenDiffuse;
761         int tex_Texture_ScreenSpecular;
762         int tex_Texture_ReflectMask;
763         int tex_Texture_ReflectCube;
764         int tex_Texture_BounceGrid;
765         /// locations of detected uniforms in program object, or -1 if not found
766         int loc_Texture_First;
767         int loc_Texture_Second;
768         int loc_Texture_GammaRamps;
769         int loc_Texture_Normal;
770         int loc_Texture_Color;
771         int loc_Texture_Gloss;
772         int loc_Texture_Glow;
773         int loc_Texture_SecondaryNormal;
774         int loc_Texture_SecondaryColor;
775         int loc_Texture_SecondaryGloss;
776         int loc_Texture_SecondaryGlow;
777         int loc_Texture_Pants;
778         int loc_Texture_Shirt;
779         int loc_Texture_FogHeightTexture;
780         int loc_Texture_FogMask;
781         int loc_Texture_Lightmap;
782         int loc_Texture_Deluxemap;
783         int loc_Texture_Attenuation;
784         int loc_Texture_Cube;
785         int loc_Texture_Refraction;
786         int loc_Texture_Reflection;
787         int loc_Texture_ShadowMap2D;
788         int loc_Texture_CubeProjection;
789         int loc_Texture_ScreenDepth;
790         int loc_Texture_ScreenNormalMap;
791         int loc_Texture_ScreenDiffuse;
792         int loc_Texture_ScreenSpecular;
793         int loc_Texture_ReflectMask;
794         int loc_Texture_ReflectCube;
795         int loc_Texture_BounceGrid;
796         int loc_Alpha;
797         int loc_BloomBlur_Parameters;
798         int loc_ClientTime;
799         int loc_Color_Ambient;
800         int loc_Color_Diffuse;
801         int loc_Color_Specular;
802         int loc_Color_Glow;
803         int loc_Color_Pants;
804         int loc_Color_Shirt;
805         int loc_DeferredColor_Ambient;
806         int loc_DeferredColor_Diffuse;
807         int loc_DeferredColor_Specular;
808         int loc_DeferredMod_Diffuse;
809         int loc_DeferredMod_Specular;
810         int loc_DistortScaleRefractReflect;
811         int loc_EyePosition;
812         int loc_FogColor;
813         int loc_FogHeightFade;
814         int loc_FogPlane;
815         int loc_FogPlaneViewDist;
816         int loc_FogRangeRecip;
817         int loc_LightColor;
818         int loc_LightDir;
819         int loc_LightPosition;
820         int loc_OffsetMapping_ScaleSteps;
821         int loc_PixelSize;
822         int loc_ReflectColor;
823         int loc_ReflectFactor;
824         int loc_ReflectOffset;
825         int loc_RefractColor;
826         int loc_Saturation;
827         int loc_ScreenCenterRefractReflect;
828         int loc_ScreenScaleRefractReflect;
829         int loc_ScreenToDepth;
830         int loc_ShadowMap_Parameters;
831         int loc_ShadowMap_TextureScale;
832         int loc_SpecularPower;
833         int loc_UserVec1;
834         int loc_UserVec2;
835         int loc_UserVec3;
836         int loc_UserVec4;
837         int loc_ViewTintColor;
838         int loc_ViewToLight;
839         int loc_ModelToLight;
840         int loc_TexMatrix;
841         int loc_BackgroundTexMatrix;
842         int loc_ModelViewProjectionMatrix;
843         int loc_ModelViewMatrix;
844         int loc_PixelToScreenTexCoord;
845         int loc_ModelToReflectCube;
846         int loc_ShadowMapMatrix;
847         int loc_BloomColorSubtract;
848         int loc_NormalmapScrollBlend;
849         int loc_BounceGridMatrix;
850         int loc_BounceGridIntensity;
851 }
852 r_glsl_permutation_t;
853
854 #define SHADERPERMUTATION_HASHSIZE 256
855
856
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
859 enum
860 {
861         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
867         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
868 };
869 #define SHADERSTATICPARMS_COUNT 7
870
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
873
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
877 {
878         static int r_compileshader_staticparms_save[1];
879         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
881
882         // detect all
883         if (r_glsl_saturation_redcompensate.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885         if (r_glsl_vertextextureblend_usebothalphas.integer)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887         if (r_shadow_glossexact.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889         if (r_glsl_postprocess.integer)
890         {
891                 if (r_glsl_postprocess_uservec1_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893                 if (r_glsl_postprocess_uservec2_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895                 if (r_glsl_postprocess_uservec3_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897                 if (r_glsl_postprocess_uservec4_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
899         }
900         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
901 }
902
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
906         else \
907                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
909 {
910         shaderstaticparms_count = 0;
911
912         // emit all
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
920 }
921
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
928
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
930 {
931         //unsigned int hashdepth = 0;
932         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933         r_glsl_permutation_t *p;
934         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
935         {
936                 if (p->mode == mode && p->permutation == permutation)
937                 {
938                         //if (hashdepth > 10)
939                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
940                         return p;
941                 }
942                 //hashdepth++;
943         }
944         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
945         p->mode = mode;
946         p->permutation = permutation;
947         p->hashnext = r_glsl_permutationhash[mode][hashindex];
948         r_glsl_permutationhash[mode][hashindex] = p;
949         //if (hashdepth > 10)
950         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
951         return p;
952 }
953
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
955 {
956         char *shaderstring;
957         if (!filename || !filename[0])
958                 return NULL;
959         if (!strcmp(filename, "glsl/default.glsl"))
960         {
961                 if (!glslshaderstring)
962                 {
963                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964                         if (glslshaderstring)
965                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
966                         else
967                                 glslshaderstring = (char *)builtinshaderstring;
968                 }
969                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
971                 return shaderstring;
972         }
973         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
974         if (shaderstring)
975         {
976                 if (printfromdisknotice)
977                         Con_DPrintf("from disk %s... ", filename);
978                 return shaderstring;
979         }
980         return shaderstring;
981 }
982
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
984 {
985         int i;
986         int sampler;
987         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988         char *vertexstring, *geometrystring, *fragmentstring;
989         char permutationname[256];
990         int vertstrings_count = 0;
991         int geomstrings_count = 0;
992         int fragstrings_count = 0;
993         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996
997         if (p->compiled)
998                 return;
999         p->compiled = true;
1000         p->program = 0;
1001
1002         permutationname[0] = 0;
1003         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1006
1007         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1008
1009         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010         if(vid.support.gl20shaders130)
1011         {
1012                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1018         }
1019
1020         // the first pretext is which type of shader to compile as
1021         // (later these will all be bound together as a program object)
1022         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1025
1026         // the second pretext is the mode (for example a light source)
1027         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1031
1032         // now add all the permutation pretexts
1033         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1034         {
1035                 if (permutation & (1<<i))
1036                 {
1037                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1041                 }
1042                 else
1043                 {
1044                         // keep line numbers correct
1045                         vertstrings_list[vertstrings_count++] = "\n";
1046                         geomstrings_list[geomstrings_count++] = "\n";
1047                         fragstrings_list[fragstrings_count++] = "\n";
1048                 }
1049         }
1050
1051         // add static parms
1052         R_CompileShader_AddStaticParms(mode, permutation);
1053         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054         vertstrings_count += shaderstaticparms_count;
1055         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056         geomstrings_count += shaderstaticparms_count;
1057         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         fragstrings_count += shaderstaticparms_count;
1059
1060         // now append the shader text itself
1061         vertstrings_list[vertstrings_count++] = vertexstring;
1062         geomstrings_list[geomstrings_count++] = geometrystring;
1063         fragstrings_list[fragstrings_count++] = fragmentstring;
1064
1065         // if any sources were NULL, clear the respective list
1066         if (!vertexstring)
1067                 vertstrings_count = 0;
1068         if (!geometrystring)
1069                 geomstrings_count = 0;
1070         if (!fragmentstring)
1071                 fragstrings_count = 0;
1072
1073         // compile the shader program
1074         if (vertstrings_count + geomstrings_count + fragstrings_count)
1075                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1076         if (p->program)
1077         {
1078                 CHECKGLERROR
1079                 qglUseProgram(p->program);CHECKGLERROR
1080                 // look up all the uniform variable names we care about, so we don't
1081                 // have to look them up every time we set them
1082
1083                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1084                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1085                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1087                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1088                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1089                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1090                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1095                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1096                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1098                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1102                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1103                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1104                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1114                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1116                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1117                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1118                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1119                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1120                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1121                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1122                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1129                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1130                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1131                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1132                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1134                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1135                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1136                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1137                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1139                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1140                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1141                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1142                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1143                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1144                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1147                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1150                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1151                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1152                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1153                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1154                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1155                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1156                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1157                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1158                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168                 // initialize the samplers to refer to the texture units we use
1169                 p->tex_Texture_First = -1;
1170                 p->tex_Texture_Second = -1;
1171                 p->tex_Texture_GammaRamps = -1;
1172                 p->tex_Texture_Normal = -1;
1173                 p->tex_Texture_Color = -1;
1174                 p->tex_Texture_Gloss = -1;
1175                 p->tex_Texture_Glow = -1;
1176                 p->tex_Texture_SecondaryNormal = -1;
1177                 p->tex_Texture_SecondaryColor = -1;
1178                 p->tex_Texture_SecondaryGloss = -1;
1179                 p->tex_Texture_SecondaryGlow = -1;
1180                 p->tex_Texture_Pants = -1;
1181                 p->tex_Texture_Shirt = -1;
1182                 p->tex_Texture_FogHeightTexture = -1;
1183                 p->tex_Texture_FogMask = -1;
1184                 p->tex_Texture_Lightmap = -1;
1185                 p->tex_Texture_Deluxemap = -1;
1186                 p->tex_Texture_Attenuation = -1;
1187                 p->tex_Texture_Cube = -1;
1188                 p->tex_Texture_Refraction = -1;
1189                 p->tex_Texture_Reflection = -1;
1190                 p->tex_Texture_ShadowMap2D = -1;
1191                 p->tex_Texture_CubeProjection = -1;
1192                 p->tex_Texture_ScreenDepth = -1;
1193                 p->tex_Texture_ScreenNormalMap = -1;
1194                 p->tex_Texture_ScreenDiffuse = -1;
1195                 p->tex_Texture_ScreenSpecular = -1;
1196                 p->tex_Texture_ReflectMask = -1;
1197                 p->tex_Texture_ReflectCube = -1;
1198                 p->tex_Texture_BounceGrid = -1;
1199                 sampler = 0;
1200                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1201                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1202                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1203                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1204                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1205                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1206                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1207                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1211                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1212                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1213                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1215                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1216                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1217                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1218                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1219                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1220                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1221                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1222                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1223                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1224                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1227                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1228                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1229                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1230                 CHECKGLERROR
1231                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1232         }
1233         else
1234                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1235
1236         // free the strings
1237         if (vertexstring)
1238                 Mem_Free(vertexstring);
1239         if (geometrystring)
1240                 Mem_Free(geometrystring);
1241         if (fragmentstring)
1242                 Mem_Free(fragmentstring);
1243 }
1244
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1246 {
1247         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248         if (r_glsl_permutation != perm)
1249         {
1250                 r_glsl_permutation = perm;
1251                 if (!r_glsl_permutation->program)
1252                 {
1253                         if (!r_glsl_permutation->compiled)
1254                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1255                         if (!r_glsl_permutation->program)
1256                         {
1257                                 // remove features until we find a valid permutation
1258                                 int i;
1259                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1260                                 {
1261                                         // reduce i more quickly whenever it would not remove any bits
1262                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263                                         if (!(permutation & j))
1264                                                 continue;
1265                                         permutation -= j;
1266                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267                                         if (!r_glsl_permutation->compiled)
1268                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                                         if (r_glsl_permutation->program)
1270                                                 break;
1271                                 }
1272                                 if (i >= SHADERPERMUTATION_COUNT)
1273                                 {
1274                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276                                         qglUseProgram(0);CHECKGLERROR
1277                                         return; // no bit left to clear, entire mode is broken
1278                                 }
1279                         }
1280                 }
1281                 CHECKGLERROR
1282                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1283         }
1284         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1287 }
1288
1289 #ifdef SUPPORTD3D
1290
1291 #ifdef SUPPORTD3D
1292 #include <d3d9.h>
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1295 #endif
1296
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1299 {
1300         /// hash lookup data
1301         struct r_hlsl_permutation_s *hashnext;
1302         unsigned int mode;
1303         unsigned int permutation;
1304
1305         /// indicates if we have tried compiling this permutation already
1306         qboolean compiled;
1307         /// NULL if compilation failed
1308         IDirect3DVertexShader9 *vertexshader;
1309         IDirect3DPixelShader9 *pixelshader;
1310 }
1311 r_hlsl_permutation_t;
1312
1313 typedef enum D3DVSREGISTER_e
1314 {
1315         D3DVSREGISTER_TexMatrix = 0, // float4x4
1316         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320         D3DVSREGISTER_ModelToLight = 20, // float4x4
1321         D3DVSREGISTER_EyePosition = 24,
1322         D3DVSREGISTER_FogPlane = 25,
1323         D3DVSREGISTER_LightDir = 26,
1324         D3DVSREGISTER_LightPosition = 27,
1325 }
1326 D3DVSREGISTER_t;
1327
1328 typedef enum D3DPSREGISTER_e
1329 {
1330         D3DPSREGISTER_Alpha = 0,
1331         D3DPSREGISTER_BloomBlur_Parameters = 1,
1332         D3DPSREGISTER_ClientTime = 2,
1333         D3DPSREGISTER_Color_Ambient = 3,
1334         D3DPSREGISTER_Color_Diffuse = 4,
1335         D3DPSREGISTER_Color_Specular = 5,
1336         D3DPSREGISTER_Color_Glow = 6,
1337         D3DPSREGISTER_Color_Pants = 7,
1338         D3DPSREGISTER_Color_Shirt = 8,
1339         D3DPSREGISTER_DeferredColor_Ambient = 9,
1340         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341         D3DPSREGISTER_DeferredColor_Specular = 11,
1342         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343         D3DPSREGISTER_DeferredMod_Specular = 13,
1344         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345         D3DPSREGISTER_EyePosition = 15, // unused
1346         D3DPSREGISTER_FogColor = 16,
1347         D3DPSREGISTER_FogHeightFade = 17,
1348         D3DPSREGISTER_FogPlane = 18,
1349         D3DPSREGISTER_FogPlaneViewDist = 19,
1350         D3DPSREGISTER_FogRangeRecip = 20,
1351         D3DPSREGISTER_LightColor = 21,
1352         D3DPSREGISTER_LightDir = 22, // unused
1353         D3DPSREGISTER_LightPosition = 23,
1354         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355         D3DPSREGISTER_PixelSize = 25,
1356         D3DPSREGISTER_ReflectColor = 26,
1357         D3DPSREGISTER_ReflectFactor = 27,
1358         D3DPSREGISTER_ReflectOffset = 28,
1359         D3DPSREGISTER_RefractColor = 29,
1360         D3DPSREGISTER_Saturation = 30,
1361         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363         D3DPSREGISTER_ScreenToDepth = 33,
1364         D3DPSREGISTER_ShadowMap_Parameters = 34,
1365         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366         D3DPSREGISTER_SpecularPower = 36,
1367         D3DPSREGISTER_UserVec1 = 37,
1368         D3DPSREGISTER_UserVec2 = 38,
1369         D3DPSREGISTER_UserVec3 = 39,
1370         D3DPSREGISTER_UserVec4 = 40,
1371         D3DPSREGISTER_ViewTintColor = 41,
1372         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373         D3DPSREGISTER_BloomColorSubtract = 43,
1374         D3DPSREGISTER_ViewToLight = 44, // float4x4
1375         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376         D3DPSREGISTER_NormalmapScrollBlend = 52,
1377         // next at 53
1378 }
1379 D3DPSREGISTER_t;
1380
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1387
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1389 {
1390         //unsigned int hashdepth = 0;
1391         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392         r_hlsl_permutation_t *p;
1393         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1394         {
1395                 if (p->mode == mode && p->permutation == permutation)
1396                 {
1397                         //if (hashdepth > 10)
1398                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1399                         return p;
1400                 }
1401                 //hashdepth++;
1402         }
1403         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1404         p->mode = mode;
1405         p->permutation = permutation;
1406         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407         r_hlsl_permutationhash[mode][hashindex] = p;
1408         //if (hashdepth > 10)
1409         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1410         return p;
1411 }
1412
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1414 {
1415         char *shaderstring;
1416         if (!filename || !filename[0])
1417                 return NULL;
1418         if (!strcmp(filename, "hlsl/default.hlsl"))
1419         {
1420                 if (!hlslshaderstring)
1421                 {
1422                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423                         if (hlslshaderstring)
1424                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1425                         else
1426                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1427                 }
1428                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430                 return shaderstring;
1431         }
1432         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1433         if (shaderstring)
1434         {
1435                 if (printfromdisknotice)
1436                         Con_DPrintf("from disk %s... ", filename);
1437                 return shaderstring;
1438         }
1439         return shaderstring;
1440 }
1441
1442 #include <d3dx9.h>
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1445
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1447 {
1448         DWORD *vsbin = NULL;
1449         DWORD *psbin = NULL;
1450         fs_offset_t vsbinsize;
1451         fs_offset_t psbinsize;
1452 //      IDirect3DVertexShader9 *vs = NULL;
1453 //      IDirect3DPixelShader9 *ps = NULL;
1454         ID3DXBuffer *vslog = NULL;
1455         ID3DXBuffer *vsbuffer = NULL;
1456         ID3DXConstantTable *vsconstanttable = NULL;
1457         ID3DXBuffer *pslog = NULL;
1458         ID3DXBuffer *psbuffer = NULL;
1459         ID3DXConstantTable *psconstanttable = NULL;
1460         int vsresult = 0;
1461         int psresult = 0;
1462         char temp[MAX_INPUTLINE];
1463         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464         qboolean debugshader = gl_paranoid.integer != 0;
1465         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467         if (!debugshader)
1468         {
1469                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1471         }
1472         if ((!vsbin && vertstring) || (!psbin && fragstring))
1473         {
1474                 const char* dllnames_d3dx9 [] =
1475                 {
1476                         "d3dx9_43.dll",
1477                         "d3dx9_42.dll",
1478                         "d3dx9_41.dll",
1479                         "d3dx9_40.dll",
1480                         "d3dx9_39.dll",
1481                         "d3dx9_38.dll",
1482                         "d3dx9_37.dll",
1483                         "d3dx9_36.dll",
1484                         "d3dx9_35.dll",
1485                         "d3dx9_34.dll",
1486                         "d3dx9_33.dll",
1487                         "d3dx9_32.dll",
1488                         "d3dx9_31.dll",
1489                         "d3dx9_30.dll",
1490                         "d3dx9_29.dll",
1491                         "d3dx9_28.dll",
1492                         "d3dx9_27.dll",
1493                         "d3dx9_26.dll",
1494                         "d3dx9_25.dll",
1495                         "d3dx9_24.dll",
1496                         NULL
1497                 };
1498                 dllhandle_t d3dx9_dll = NULL;
1499                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502                 dllfunction_t d3dx9_dllfuncs[] =
1503                 {
1504                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1505                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1506                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1507                         {NULL, NULL}
1508                 };
1509                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1510                 {
1511                         DWORD shaderflags = 0;
1512                         if (debugshader)
1513                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516                         if (vertstring && vertstring[0])
1517                         {
1518                                 if (debugshader)
1519                                 {
1520 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1524                                 }
1525                                 else
1526                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527                                 if (vsbuffer)
1528                                 {
1529                                         vsbinsize = vsbuffer->GetBufferSize();
1530                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532                                         vsbuffer->Release();
1533                                 }
1534                                 if (vslog)
1535                                 {
1536                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1538                                         vslog->Release();
1539                                 }
1540                         }
1541                         if (fragstring && fragstring[0])
1542                         {
1543                                 if (debugshader)
1544                                 {
1545 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1549                                 }
1550                                 else
1551                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552                                 if (psbuffer)
1553                                 {
1554                                         psbinsize = psbuffer->GetBufferSize();
1555                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557                                         psbuffer->Release();
1558                                 }
1559                                 if (pslog)
1560                                 {
1561                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1563                                         pslog->Release();
1564                                 }
1565                         }
1566                         Sys_UnloadLibrary(&d3dx9_dll);
1567                 }
1568                 else
1569                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1570         }
1571         if (vsbin && psbin)
1572         {
1573                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574                 if (FAILED(vsresult))
1575                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577                 if (FAILED(psresult))
1578                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1579         }
1580         // free the shader data
1581         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1583 }
1584
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1586 {
1587         int i;
1588         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589         int vertstring_length = 0;
1590         int geomstring_length = 0;
1591         int fragstring_length = 0;
1592         char *t;
1593         char *vertexstring, *geometrystring, *fragmentstring;
1594         char *vertstring, *geomstring, *fragstring;
1595         char permutationname[256];
1596         char cachename[256];
1597         int vertstrings_count = 0;
1598         int geomstrings_count = 0;
1599         int fragstrings_count = 0;
1600         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603
1604         if (p->compiled)
1605                 return;
1606         p->compiled = true;
1607         p->vertexshader = NULL;
1608         p->pixelshader = NULL;
1609
1610         permutationname[0] = 0;
1611         cachename[0] = 0;
1612         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1615
1616         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617         strlcat(cachename, "hlsl/", sizeof(cachename));
1618
1619         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620         vertstrings_count = 0;
1621         geomstrings_count = 0;
1622         fragstrings_count = 0;
1623         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1626
1627         // the first pretext is which type of shader to compile as
1628         // (later these will all be bound together as a program object)
1629         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1632
1633         // the second pretext is the mode (for example a light source)
1634         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638         strlcat(cachename, modeinfo->name, sizeof(cachename));
1639
1640         // now add all the permutation pretexts
1641         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1642         {
1643                 if (permutation & (1<<i))
1644                 {
1645                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1650                 }
1651                 else
1652                 {
1653                         // keep line numbers correct
1654                         vertstrings_list[vertstrings_count++] = "\n";
1655                         geomstrings_list[geomstrings_count++] = "\n";
1656                         fragstrings_list[fragstrings_count++] = "\n";
1657                 }
1658         }
1659
1660         // add static parms
1661         R_CompileShader_AddStaticParms(mode, permutation);
1662         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663         vertstrings_count += shaderstaticparms_count;
1664         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665         geomstrings_count += shaderstaticparms_count;
1666         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         fragstrings_count += shaderstaticparms_count;
1668
1669         // replace spaces in the cachename with _ characters
1670         for (i = 0;cachename[i];i++)
1671                 if (cachename[i] == ' ')
1672                         cachename[i] = '_';
1673
1674         // now append the shader text itself
1675         vertstrings_list[vertstrings_count++] = vertexstring;
1676         geomstrings_list[geomstrings_count++] = geometrystring;
1677         fragstrings_list[fragstrings_count++] = fragmentstring;
1678
1679         // if any sources were NULL, clear the respective list
1680         if (!vertexstring)
1681                 vertstrings_count = 0;
1682         if (!geometrystring)
1683                 geomstrings_count = 0;
1684         if (!fragmentstring)
1685                 fragstrings_count = 0;
1686
1687         vertstring_length = 0;
1688         for (i = 0;i < vertstrings_count;i++)
1689                 vertstring_length += strlen(vertstrings_list[i]);
1690         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1693
1694         geomstring_length = 0;
1695         for (i = 0;i < geomstrings_count;i++)
1696                 geomstring_length += strlen(geomstrings_list[i]);
1697         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1700
1701         fragstring_length = 0;
1702         for (i = 0;i < fragstrings_count;i++)
1703                 fragstring_length += strlen(fragstrings_list[i]);
1704         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1707
1708         // try to load the cached shader, or generate one
1709         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1710
1711         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1713         else
1714                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1715
1716         // free the strings
1717         if (vertstring)
1718                 Mem_Free(vertstring);
1719         if (geomstring)
1720                 Mem_Free(geomstring);
1721         if (fragstring)
1722                 Mem_Free(fragstring);
1723         if (vertexstring)
1724                 Mem_Free(vertexstring);
1725         if (geometrystring)
1726                 Mem_Free(geometrystring);
1727         if (fragmentstring)
1728                 Mem_Free(fragmentstring);
1729 }
1730
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 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);}
1734 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);}
1735 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);}
1736 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);}
1737
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1744
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1746 {
1747         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748         if (r_hlsl_permutation != perm)
1749         {
1750                 r_hlsl_permutation = perm;
1751                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752                 {
1753                         if (!r_hlsl_permutation->compiled)
1754                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1755                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1756                         {
1757                                 // remove features until we find a valid permutation
1758                                 int i;
1759                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1760                                 {
1761                                         // reduce i more quickly whenever it would not remove any bits
1762                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763                                         if (!(permutation & j))
1764                                                 continue;
1765                                         permutation -= j;
1766                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767                                         if (!r_hlsl_permutation->compiled)
1768                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1769                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1770                                                 break;
1771                                 }
1772                                 if (i >= SHADERPERMUTATION_COUNT)
1773                                 {
1774                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776                                         return; // no bit left to clear, entire mode is broken
1777                                 }
1778                         }
1779                 }
1780                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1782         }
1783         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1786 }
1787 #endif
1788
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1790 {
1791         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1795 }
1796
1797 void R_GLSL_Restart_f(void)
1798 {
1799         unsigned int i, limit;
1800         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801                 Mem_Free(glslshaderstring);
1802         glslshaderstring = NULL;
1803         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804                 Mem_Free(hlslshaderstring);
1805         hlslshaderstring = NULL;
1806         switch(vid.renderpath)
1807         {
1808         case RENDERPATH_D3D9:
1809 #ifdef SUPPORTD3D
1810                 {
1811                         r_hlsl_permutation_t *p;
1812                         r_hlsl_permutation = NULL;
1813                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814                         for (i = 0;i < limit;i++)
1815                         {
1816                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1817                                 {
1818                                         if (p->vertexshader)
1819                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1820                                         if (p->pixelshader)
1821                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1822                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1823                                 }
1824                         }
1825                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1826                 }
1827 #endif
1828                 break;
1829         case RENDERPATH_D3D10:
1830                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1831                 break;
1832         case RENDERPATH_D3D11:
1833                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1834                 break;
1835         case RENDERPATH_GL20:
1836         case RENDERPATH_GLES2:
1837                 {
1838                         r_glsl_permutation_t *p;
1839                         r_glsl_permutation = NULL;
1840                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841                         for (i = 0;i < limit;i++)
1842                         {
1843                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1844                                 {
1845                                         GL_Backend_FreeProgram(p->program);
1846                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1847                                 }
1848                         }
1849                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1850                 }
1851                 break;
1852         case RENDERPATH_GL13:
1853         case RENDERPATH_GL11:
1854                 break;
1855         case RENDERPATH_SOFT:
1856                 break;
1857         }
1858 }
1859
1860 void R_GLSL_DumpShader_f(void)
1861 {
1862         int i;
1863         qfile_t *file;
1864
1865         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1866         if (file)
1867         {
1868                 FS_Print(file, "/* The engine may define the following macros:\n");
1869                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1870                 for (i = 0;i < SHADERMODE_COUNT;i++)
1871                         FS_Print(file, glslshadermodeinfo[i].pretext);
1872                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1873                         FS_Print(file, shaderpermutationinfo[i].pretext);
1874                 FS_Print(file, "*/\n");
1875                 FS_Print(file, builtinshaderstring);
1876                 FS_Close(file);
1877                 Con_Printf("glsl/default.glsl written\n");
1878         }
1879         else
1880                 Con_Printf("failed to write to glsl/default.glsl\n");
1881
1882         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1883         if (file)
1884         {
1885                 FS_Print(file, "/* The engine may define the following macros:\n");
1886                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887                 for (i = 0;i < SHADERMODE_COUNT;i++)
1888                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1889                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890                         FS_Print(file, shaderpermutationinfo[i].pretext);
1891                 FS_Print(file, "*/\n");
1892                 FS_Print(file, builtinhlslshaderstring);
1893                 FS_Close(file);
1894                 Con_Printf("hlsl/default.hlsl written\n");
1895         }
1896         else
1897                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1898 }
1899
1900 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1901 {
1902         if (!second)
1903                 texturemode = GL_MODULATE;
1904         switch (vid.renderpath)
1905         {
1906         case RENDERPATH_D3D9:
1907 #ifdef SUPPORTD3D
1908                 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))));
1909                 R_Mesh_TexBind(GL20TU_FIRST , first );
1910                 R_Mesh_TexBind(GL20TU_SECOND, second);
1911 #endif
1912                 break;
1913         case RENDERPATH_D3D10:
1914                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1915                 break;
1916         case RENDERPATH_D3D11:
1917                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918                 break;
1919         case RENDERPATH_GL20:
1920         case RENDERPATH_GLES2:
1921                 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))));
1922                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1923                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1924                 break;
1925         case RENDERPATH_GL13:
1926                 R_Mesh_TexBind(0, first );
1927                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1928                 R_Mesh_TexBind(1, second);
1929                 if (second)
1930                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1931                 break;
1932         case RENDERPATH_GL11:
1933                 R_Mesh_TexBind(0, first );
1934                 break;
1935         case RENDERPATH_SOFT:
1936                 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))));
1937                 R_Mesh_TexBind(GL20TU_FIRST , first );
1938                 R_Mesh_TexBind(GL20TU_SECOND, second);
1939                 break;
1940         }
1941 }
1942
1943 void R_SetupShader_DepthOrShadow(void)
1944 {
1945         switch (vid.renderpath)
1946         {
1947         case RENDERPATH_D3D9:
1948 #ifdef SUPPORTD3D
1949                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1950 #endif
1951                 break;
1952         case RENDERPATH_D3D10:
1953                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1954                 break;
1955         case RENDERPATH_D3D11:
1956                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_GL20:
1959         case RENDERPATH_GLES2:
1960                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1961                 break;
1962         case RENDERPATH_GL13:
1963                 R_Mesh_TexBind(0, 0);
1964                 R_Mesh_TexBind(1, 0);
1965                 break;
1966         case RENDERPATH_GL11:
1967                 R_Mesh_TexBind(0, 0);
1968                 break;
1969         case RENDERPATH_SOFT:
1970                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1971                 break;
1972         }
1973 }
1974
1975 void R_SetupShader_ShowDepth(void)
1976 {
1977         switch (vid.renderpath)
1978         {
1979         case RENDERPATH_D3D9:
1980 #ifdef SUPPORTHLSL
1981                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1982 #endif
1983                 break;
1984         case RENDERPATH_D3D10:
1985                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1986                 break;
1987         case RENDERPATH_D3D11:
1988                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1989                 break;
1990         case RENDERPATH_GL20:
1991         case RENDERPATH_GLES2:
1992                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1993                 break;
1994         case RENDERPATH_GL13:
1995                 break;
1996         case RENDERPATH_GL11:
1997                 break;
1998         case RENDERPATH_SOFT:
1999                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2000                 break;
2001         }
2002 }
2003
2004 extern qboolean r_shadow_usingdeferredprepass;
2005 extern cvar_t r_shadow_deferred_8bitrange;
2006 extern rtexture_t *r_shadow_attenuationgradienttexture;
2007 extern rtexture_t *r_shadow_attenuation2dtexture;
2008 extern rtexture_t *r_shadow_attenuation3dtexture;
2009 extern qboolean r_shadow_usingshadowmap2d;
2010 extern qboolean r_shadow_usingshadowmaportho;
2011 extern float r_shadow_shadowmap_texturescale[2];
2012 extern float r_shadow_shadowmap_parameters[4];
2013 extern qboolean r_shadow_shadowmapvsdct;
2014 extern qboolean r_shadow_shadowmapsampler;
2015 extern int r_shadow_shadowmappcf;
2016 extern rtexture_t *r_shadow_shadowmap2dtexture;
2017 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2018 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2019 extern matrix4x4_t r_shadow_shadowmapmatrix;
2020 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2021 extern int r_shadow_prepass_width;
2022 extern int r_shadow_prepass_height;
2023 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2024 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2025 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2026 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2027 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2028
2029 #define BLENDFUNC_ALLOWS_COLORMOD      1
2030 #define BLENDFUNC_ALLOWS_FOG           2
2031 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2032 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2033 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2034 static int R_BlendFuncFlags(int src, int dst)
2035 {
2036         int r = 0;
2037
2038         // a blendfunc allows colormod if:
2039         // a) it can never keep the destination pixel invariant, or
2040         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2041         // this is to prevent unintended side effects from colormod
2042
2043         // a blendfunc allows fog if:
2044         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2045         // this is to prevent unintended side effects from fog
2046
2047         // these checks are the output of fogeval.pl
2048
2049         r |= BLENDFUNC_ALLOWS_COLORMOD;
2050         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2051         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2052         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2054         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2056         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2059         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2060         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2061         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2063         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2066         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2070         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071
2072         return r;
2073 }
2074
2075 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)
2076 {
2077         // select a permutation of the lighting shader appropriate to this
2078         // combination of texture, entity, light source, and fogging, only use the
2079         // minimum features necessary to avoid wasting rendering time in the
2080         // fragment shader on features that are not being used
2081         unsigned int permutation = 0;
2082         unsigned int mode = 0;
2083         int blendfuncflags;
2084         static float dummy_colormod[3] = {1, 1, 1};
2085         float *colormod = rsurface.colormod;
2086         float m16f[16];
2087         matrix4x4_t tempmatrix;
2088         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2089         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2090                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2091         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2092                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2093         if (rsurfacepass == RSURFPASS_BACKGROUND)
2094         {
2095                 // distorted background
2096                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2097                 {
2098                         mode = SHADERMODE_WATER;
2099                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2100                         {
2101                                 // this is the right thing to do for wateralpha
2102                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2103                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2104                         }
2105                         else
2106                         {
2107                                 // this is the right thing to do for entity alpha
2108                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2109                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110                         }
2111                 }
2112                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2113                 {
2114                         mode = SHADERMODE_REFRACTION;
2115                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2116                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2117                 }
2118                 else
2119                 {
2120                         mode = SHADERMODE_GENERIC;
2121                         permutation |= SHADERPERMUTATION_DIFFUSE;
2122                         GL_BlendFunc(GL_ONE, GL_ZERO);
2123                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2124                 }
2125         }
2126         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2127         {
2128                 if (r_glsl_offsetmapping.integer)
2129                 {
2130                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2131                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2132                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2133                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2134                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2135                         {
2136                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2137                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2138                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2139                         }
2140                 }
2141                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2142                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2143                 // normalmap (deferred prepass), may use alpha test on diffuse
2144                 mode = SHADERMODE_DEFERREDGEOMETRY;
2145                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2146                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2147                 GL_BlendFunc(GL_ONE, GL_ZERO);
2148                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149         }
2150         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2151         {
2152                 if (r_glsl_offsetmapping.integer)
2153                 {
2154                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2155                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2156                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2157                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2158                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2159                         {
2160                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2161                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2162                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2163                         }
2164                 }
2165                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2166                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2167                 // light source
2168                 mode = SHADERMODE_LIGHTSOURCE;
2169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2172                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2173                 if (diffusescale > 0)
2174                         permutation |= SHADERPERMUTATION_DIFFUSE;
2175                 if (specularscale > 0)
2176                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2177                 if (r_refdef.fogenabled)
2178                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2179                 if (rsurface.texture->colormapping)
2180                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2181                 if (r_shadow_usingshadowmap2d)
2182                 {
2183                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2184                         if(r_shadow_shadowmapvsdct)
2185                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2186
2187                         if (r_shadow_shadowmapsampler)
2188                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2189                         if (r_shadow_shadowmappcf > 1)
2190                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2191                         else if (r_shadow_shadowmappcf)
2192                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2193                 }
2194                 if (rsurface.texture->reflectmasktexture)
2195                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2196                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2197                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2198         }
2199         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2200         {
2201                 if (r_glsl_offsetmapping.integer)
2202                 {
2203                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2204                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2205                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2206                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2207                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2208                         {
2209                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2210                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2211                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2212                         }
2213                 }
2214                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2215                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2216                 // unshaded geometry (fullbright or ambient model lighting)
2217                 mode = SHADERMODE_FLATCOLOR;
2218                 ambientscale = diffusescale = specularscale = 0;
2219                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2220                         permutation |= SHADERPERMUTATION_GLOW;
2221                 if (r_refdef.fogenabled)
2222                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2223                 if (rsurface.texture->colormapping)
2224                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2225                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2226                 {
2227                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2228                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2229
2230                         if (r_shadow_shadowmapsampler)
2231                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2232                         if (r_shadow_shadowmappcf > 1)
2233                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2234                         else if (r_shadow_shadowmappcf)
2235                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2236                 }
2237                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2238                         permutation |= SHADERPERMUTATION_REFLECTION;
2239                 if (rsurface.texture->reflectmasktexture)
2240                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2241                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2242                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2243         }
2244         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2245         {
2246                 if (r_glsl_offsetmapping.integer)
2247                 {
2248                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2249                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2250                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2251                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2252                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2253                         {
2254                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2255                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2256                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2257                         }
2258                 }
2259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2260                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2261                 // directional model lighting
2262                 mode = SHADERMODE_LIGHTDIRECTION;
2263                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2264                         permutation |= SHADERPERMUTATION_GLOW;
2265                 permutation |= SHADERPERMUTATION_DIFFUSE;
2266                 if (specularscale > 0)
2267                         permutation |= SHADERPERMUTATION_SPECULAR;
2268                 if (r_refdef.fogenabled)
2269                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270                 if (rsurface.texture->colormapping)
2271                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2272                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2273                 {
2274                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2276
2277                         if (r_shadow_shadowmapsampler)
2278                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2279                         if (r_shadow_shadowmappcf > 1)
2280                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2281                         else if (r_shadow_shadowmappcf)
2282                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2283                 }
2284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2285                         permutation |= SHADERPERMUTATION_REFLECTION;
2286                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2287                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2288                 if (rsurface.texture->reflectmasktexture)
2289                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2290                 if (r_shadow_bouncegridtexture)
2291                 {
2292                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2293                         if (r_shadow_bouncegriddirectional)
2294                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2295                 }
2296                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2297                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2298         }
2299         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2300         {
2301                 if (r_glsl_offsetmapping.integer)
2302                 {
2303                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2304                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2305                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2306                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2307                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2308                         {
2309                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2310                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2311                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2312                         }
2313                 }
2314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2315                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2316                 // ambient model lighting
2317                 mode = SHADERMODE_LIGHTDIRECTION;
2318                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2319                         permutation |= SHADERPERMUTATION_GLOW;
2320                 if (r_refdef.fogenabled)
2321                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2322                 if (rsurface.texture->colormapping)
2323                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2324                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2325                 {
2326                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2327                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2328
2329                         if (r_shadow_shadowmapsampler)
2330                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2331                         if (r_shadow_shadowmappcf > 1)
2332                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2333                         else if (r_shadow_shadowmappcf)
2334                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2335                 }
2336                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2337                         permutation |= SHADERPERMUTATION_REFLECTION;
2338                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2339                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2340                 if (rsurface.texture->reflectmasktexture)
2341                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2342                 if (r_shadow_bouncegridtexture)
2343                 {
2344                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2345                         if (r_shadow_bouncegriddirectional)
2346                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2347                 }
2348                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2350         }
2351         else
2352         {
2353                 if (r_glsl_offsetmapping.integer)
2354                 {
2355                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2356                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2357                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2358                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2359                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2360                         {
2361                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2362                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2363                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2364                         }
2365                 }
2366                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2367                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2368                 // lightmapped wall
2369                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2370                         permutation |= SHADERPERMUTATION_GLOW;
2371                 if (r_refdef.fogenabled)
2372                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2373                 if (rsurface.texture->colormapping)
2374                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2375                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2376                 {
2377                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2378                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2379
2380                         if (r_shadow_shadowmapsampler)
2381                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2382                         if (r_shadow_shadowmappcf > 1)
2383                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2384                         else if (r_shadow_shadowmappcf)
2385                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2386                 }
2387                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2388                         permutation |= SHADERPERMUTATION_REFLECTION;
2389                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2390                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2391                 if (rsurface.texture->reflectmasktexture)
2392                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2393                 if (FAKELIGHT_ENABLED)
2394                 {
2395                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2396                         mode = SHADERMODE_FAKELIGHT;
2397                         permutation |= SHADERPERMUTATION_DIFFUSE;
2398                         if (specularscale > 0)
2399                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2400                 }
2401                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2402                 {
2403                         // deluxemapping (light direction texture)
2404                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2405                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2406                         else
2407                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2408                         permutation |= SHADERPERMUTATION_DIFFUSE;
2409                         if (specularscale > 0)
2410                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2411                 }
2412                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2413                 {
2414                         // fake deluxemapping (uniform light direction in tangentspace)
2415                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2416                         permutation |= SHADERPERMUTATION_DIFFUSE;
2417                         if (specularscale > 0)
2418                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2419                 }
2420                 else if (rsurface.uselightmaptexture)
2421                 {
2422                         // ordinary lightmapping (q1bsp, q3bsp)
2423                         mode = SHADERMODE_LIGHTMAP;
2424                 }
2425                 else
2426                 {
2427                         // ordinary vertex coloring (q3bsp)
2428                         mode = SHADERMODE_VERTEXCOLOR;
2429                 }
2430                 if (r_shadow_bouncegridtexture)
2431                 {
2432                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2433                         if (r_shadow_bouncegriddirectional)
2434                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2435                 }
2436                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2437                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2438         }
2439         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2440                 colormod = dummy_colormod;
2441         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2442                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2443         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2444                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2445         switch(vid.renderpath)
2446         {
2447         case RENDERPATH_D3D9:
2448 #ifdef SUPPORTD3D
2449                 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);
2450                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2451                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2452                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2453                 if (mode == SHADERMODE_LIGHTSOURCE)
2454                 {
2455                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2456                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2457                 }
2458                 else
2459                 {
2460                         if (mode == SHADERMODE_LIGHTDIRECTION)
2461                         {
2462                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2463                         }
2464                 }
2465                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2466                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2467                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2468                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2469                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2470
2471                 if (mode == SHADERMODE_LIGHTSOURCE)
2472                 {
2473                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2474                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2475                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2476                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2477                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2478
2479                         // additive passes are only darkened by fog, not tinted
2480                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2481                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2482                 }
2483                 else
2484                 {
2485                         if (mode == SHADERMODE_FLATCOLOR)
2486                         {
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2488                         }
2489                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2490                         {
2491                                 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]);
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2493                                 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);
2494                                 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);
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2496                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2497                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2498                         }
2499                         else
2500                         {
2501                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2502                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2503                                 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);
2504                                 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);
2505                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2506                         }
2507                         // additive passes are only darkened by fog, not tinted
2508                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2509                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2510                         else
2511                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2512                         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);
2513                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2514                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2515                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2516                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2517                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2518                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2519                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2520                         if (mode == SHADERMODE_WATER)
2521                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2522                 }
2523                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2524                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2525                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2526                 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));
2527                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528                 if (rsurface.texture->pantstexture)
2529                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2530                 else
2531                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2532                 if (rsurface.texture->shirttexture)
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2534                 else
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2536                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2537                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2538                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2539                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2540                 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));
2541                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2542                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2543
2544                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2545                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2546                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2547                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2548                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2549                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2550                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2551                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2552                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2553                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2554                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2555                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2556                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2557                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2558                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2559                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2560                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2561                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2562                 {
2563                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2564                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2565                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2566                 }
2567                 else
2568                 {
2569                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2570                 }
2571 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2572 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2573                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2574                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2575                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2576                 {
2577                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2578                         if (rsurface.rtlight)
2579                         {
2580                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2581                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2582                         }
2583                 }
2584 #endif
2585                 break;
2586         case RENDERPATH_D3D10:
2587                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2588                 break;
2589         case RENDERPATH_D3D11:
2590                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2591                 break;
2592         case RENDERPATH_GL20:
2593         case RENDERPATH_GLES2:
2594                 if (!vid.useinterleavedarrays)
2595                 {
2596                         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);
2597                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2598                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2599                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2600                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2601                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2602                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2603                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2604                 }
2605                 else
2606                 {
2607                         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);
2608                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2609                 }
2610                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2611                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2612                 if (mode == SHADERMODE_LIGHTSOURCE)
2613                 {
2614                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2615                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2616                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2617                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2618                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2619                         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);
2620         
2621                         // additive passes are only darkened by fog, not tinted
2622                         if (r_glsl_permutation->loc_FogColor >= 0)
2623                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2624                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2625                 }
2626                 else
2627                 {
2628                         if (mode == SHADERMODE_FLATCOLOR)
2629                         {
2630                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2631                         }
2632                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2633                         {
2634                                 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]);
2635                                 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]);
2636                                 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);
2637                                 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);
2638                                 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);
2639                                 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]);
2640                                 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]);
2641                         }
2642                         else
2643                         {
2644                                 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]);
2645                                 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]);
2646                                 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);
2647                                 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);
2648                                 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);
2649                         }
2650                         // additive passes are only darkened by fog, not tinted
2651                         if (r_glsl_permutation->loc_FogColor >= 0)
2652                         {
2653                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2654                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2655                                 else
2656                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2657                         }
2658                         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);
2659                         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]);
2660                         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]);
2661                         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]);
2662                         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]);
2663                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2664                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2665                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2666                         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]);
2667                 }
2668                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2669                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2670                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2671                 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]);
2672                 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]);
2673
2674                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2675                 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));
2676                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2677                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2678                 {
2679                         if (rsurface.texture->pantstexture)
2680                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2681                         else
2682                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2683                 }
2684                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2685                 {
2686                         if (rsurface.texture->shirttexture)
2687                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2688                         else
2689                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2690                 }
2691                 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]);
2692                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2693                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2694                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2695                 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));
2696                 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]);
2697                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2698                 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);}
2699                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2700
2701                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2702                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2703                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2704                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2705                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2706                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2707                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2708                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2709                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2710                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2711                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2712                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2713                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2714                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2715                 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);
2716                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2717                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2718                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2721                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2722                 {
2723                         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);
2724                         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);
2725                         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);
2726                 }
2727                 else
2728                 {
2729                         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);
2730                 }
2731                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2732                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2733                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2734                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2735                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2736                 {
2737                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2738                         if (rsurface.rtlight)
2739                         {
2740                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2741                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2742                         }
2743                 }
2744                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2745                 CHECKGLERROR
2746                 break;
2747         case RENDERPATH_GL13:
2748         case RENDERPATH_GL11:
2749                 break;
2750         case RENDERPATH_SOFT:
2751                 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);
2752                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2753                 R_SetupShader_SetPermutationSoft(mode, permutation);
2754                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2755                 if (mode == SHADERMODE_LIGHTSOURCE)
2756                 {
2757                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2758                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2760                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2761                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2762                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2763         
2764                         // additive passes are only darkened by fog, not tinted
2765                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2766                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2767                 }
2768                 else
2769                 {
2770                         if (mode == SHADERMODE_FLATCOLOR)
2771                         {
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2773                         }
2774                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2775                         {
2776                                 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]);
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2778                                 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);
2779                                 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);
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2781                                 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]);
2782                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2783                         }
2784                         else
2785                         {
2786                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2788                                 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);
2789                                 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);
2790                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2791                         }
2792                         // additive passes are only darkened by fog, not tinted
2793                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2794                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2795                         else
2796                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2797                         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);
2798                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2799                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2800                         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]);
2801                         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]);
2802                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2803                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2804                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2805                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2806                 }
2807                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2808                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2809                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2810                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2811                 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]);
2812
2813                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2814                 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));
2815                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2816                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2817                 {
2818                         if (rsurface.texture->pantstexture)
2819                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2820                         else
2821                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2822                 }
2823                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2824                 {
2825                         if (rsurface.texture->shirttexture)
2826                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2827                         else
2828                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2829                 }
2830                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2831                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2832                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2833                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2834                 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));
2835                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2836                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2837
2838                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2839                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2840                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2841                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2842                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2843                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2844                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2845                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2846                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2847                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2848                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2849                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2850                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2851                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2852                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2853                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2854                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2855                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2856                 {
2857                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2858                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2859                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2860                 }
2861                 else
2862                 {
2863                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2864                 }
2865 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2866 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2867                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2868                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2869                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2870                 {
2871                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2872                         if (rsurface.rtlight)
2873                         {
2874                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2875                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2876                         }
2877                 }
2878                 break;
2879         }
2880 }
2881
2882 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2883 {
2884         // select a permutation of the lighting shader appropriate to this
2885         // combination of texture, entity, light source, and fogging, only use the
2886         // minimum features necessary to avoid wasting rendering time in the
2887         // fragment shader on features that are not being used
2888         unsigned int permutation = 0;
2889         unsigned int mode = 0;
2890         const float *lightcolorbase = rtlight->currentcolor;
2891         float ambientscale = rtlight->ambientscale;
2892         float diffusescale = rtlight->diffusescale;
2893         float specularscale = rtlight->specularscale;
2894         // this is the location of the light in view space
2895         vec3_t viewlightorigin;
2896         // this transforms from view space (camera) to light space (cubemap)
2897         matrix4x4_t viewtolight;
2898         matrix4x4_t lighttoview;
2899         float viewtolight16f[16];
2900         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2901         // light source
2902         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2903         if (rtlight->currentcubemap != r_texture_whitecube)
2904                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2905         if (diffusescale > 0)
2906                 permutation |= SHADERPERMUTATION_DIFFUSE;
2907         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2908                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2909         if (r_shadow_usingshadowmap2d)
2910         {
2911                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2912                 if (r_shadow_shadowmapvsdct)
2913                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2914
2915                 if (r_shadow_shadowmapsampler)
2916                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2917                 if (r_shadow_shadowmappcf > 1)
2918                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2919                 else if (r_shadow_shadowmappcf)
2920                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2921         }
2922         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2923         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2924         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2925         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2926         switch(vid.renderpath)
2927         {
2928         case RENDERPATH_D3D9:
2929 #ifdef SUPPORTD3D
2930                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2931                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2932                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2933                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2934                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2935                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2936                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2937                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2938                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2939                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2940                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2941
2942                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2943                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2944                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2945                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2946                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2947                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2948 #endif
2949                 break;
2950         case RENDERPATH_D3D10:
2951                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2952                 break;
2953         case RENDERPATH_D3D11:
2954                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2955                 break;
2956         case RENDERPATH_GL20:
2957         case RENDERPATH_GLES2:
2958                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2959                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2961                 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);
2962                 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);
2963                 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);
2964                 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]);
2965                 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]);
2966                 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));
2967                 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]);
2968                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2969
2970                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2971                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2972                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2973                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2974                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2975                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2976                 break;
2977         case RENDERPATH_GL13:
2978         case RENDERPATH_GL11:
2979                 break;
2980         case RENDERPATH_SOFT:
2981                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2982                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2983                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2984                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2985                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2986                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2987                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2988                 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]);
2989                 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));
2990                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2991                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2992
2993                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2994                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2995                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2996                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2997                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2998                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2999                 break;
3000         }
3001 }
3002
3003 #define SKINFRAME_HASH 1024
3004
3005 typedef struct
3006 {
3007         int loadsequence; // incremented each level change
3008         memexpandablearray_t array;
3009         skinframe_t *hash[SKINFRAME_HASH];
3010 }
3011 r_skinframe_t;
3012 r_skinframe_t r_skinframe;
3013
3014 void R_SkinFrame_PrepareForPurge(void)
3015 {
3016         r_skinframe.loadsequence++;
3017         // wrap it without hitting zero
3018         if (r_skinframe.loadsequence >= 200)
3019                 r_skinframe.loadsequence = 1;
3020 }
3021
3022 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3023 {
3024         if (!skinframe)
3025                 return;
3026         // mark the skinframe as used for the purging code
3027         skinframe->loadsequence = r_skinframe.loadsequence;
3028 }
3029
3030 void R_SkinFrame_Purge(void)
3031 {
3032         int i;
3033         skinframe_t *s;
3034         for (i = 0;i < SKINFRAME_HASH;i++)
3035         {
3036                 for (s = r_skinframe.hash[i];s;s = s->next)
3037                 {
3038                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3039                         {
3040                                 if (s->merged == s->base)
3041                                         s->merged = NULL;
3042                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3043                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3044                                 R_PurgeTexture(s->merged);s->merged = NULL;
3045                                 R_PurgeTexture(s->base  );s->base   = NULL;
3046                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3047                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3048                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3049                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3050                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3051                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3052                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3053                                 s->loadsequence = 0;
3054                         }
3055                 }
3056         }
3057 }
3058
3059 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3060         skinframe_t *item;
3061         char basename[MAX_QPATH];
3062
3063         Image_StripImageExtension(name, basename, sizeof(basename));
3064
3065         if( last == NULL ) {
3066                 int hashindex;
3067                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068                 item = r_skinframe.hash[hashindex];
3069         } else {
3070                 item = last->next;
3071         }
3072
3073         // linearly search through the hash bucket
3074         for( ; item ; item = item->next ) {
3075                 if( !strcmp( item->basename, basename ) ) {
3076                         return item;
3077                 }
3078         }
3079         return NULL;
3080 }
3081
3082 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3083 {
3084         skinframe_t *item;
3085         int hashindex;
3086         char basename[MAX_QPATH];
3087
3088         Image_StripImageExtension(name, basename, sizeof(basename));
3089
3090         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3091         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3092                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3093                         break;
3094
3095         if (!item) {
3096                 rtexture_t *dyntexture;
3097                 // check whether its a dynamic texture
3098                 dyntexture = CL_GetDynTexture( basename );
3099                 if (!add && !dyntexture)
3100                         return NULL;
3101                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3102                 memset(item, 0, sizeof(*item));
3103                 strlcpy(item->basename, basename, sizeof(item->basename));
3104                 item->base = dyntexture; // either NULL or dyntexture handle
3105                 item->textureflags = textureflags;
3106                 item->comparewidth = comparewidth;
3107                 item->compareheight = compareheight;
3108                 item->comparecrc = comparecrc;
3109                 item->next = r_skinframe.hash[hashindex];
3110                 r_skinframe.hash[hashindex] = item;
3111         }
3112         else if( item->base == NULL )
3113         {
3114                 rtexture_t *dyntexture;
3115                 // check whether its a dynamic texture
3116                 // 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]
3117                 dyntexture = CL_GetDynTexture( basename );
3118                 item->base = dyntexture; // either NULL or dyntexture handle
3119         }
3120
3121         R_SkinFrame_MarkUsed(item);
3122         return item;
3123 }
3124
3125 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3126         { \
3127                 unsigned long long avgcolor[5], wsum; \
3128                 int pix, comp, w; \
3129                 avgcolor[0] = 0; \
3130                 avgcolor[1] = 0; \
3131                 avgcolor[2] = 0; \
3132                 avgcolor[3] = 0; \
3133                 avgcolor[4] = 0; \
3134                 wsum = 0; \
3135                 for(pix = 0; pix < cnt; ++pix) \
3136                 { \
3137                         w = 0; \
3138                         for(comp = 0; comp < 3; ++comp) \
3139                                 w += getpixel; \
3140                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3141                         { \
3142                                 ++wsum; \
3143                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144                                 w = getpixel; \
3145                                 for(comp = 0; comp < 3; ++comp) \
3146                                         avgcolor[comp] += getpixel * w; \
3147                                 avgcolor[3] += w; \
3148                         } \
3149                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150                         avgcolor[4] += getpixel; \
3151                 } \
3152                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3153                         avgcolor[3] = 1; \
3154                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3155                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3156                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3157                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3158         }
3159
3160 extern cvar_t gl_picmip;
3161 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3162 {
3163         int j;
3164         unsigned char *pixels;
3165         unsigned char *bumppixels;
3166         unsigned char *basepixels = NULL;
3167         int basepixels_width = 0;
3168         int basepixels_height = 0;
3169         skinframe_t *skinframe;
3170         rtexture_t *ddsbase = NULL;
3171         qboolean ddshasalpha = false;
3172         float ddsavgcolor[4];
3173         char basename[MAX_QPATH];
3174         int miplevel = R_PicmipForFlags(textureflags);
3175         int savemiplevel = miplevel;
3176         int mymiplevel;
3177
3178         if (cls.state == ca_dedicated)
3179                 return NULL;
3180
3181         // return an existing skinframe if already loaded
3182         // if loading of the first image fails, don't make a new skinframe as it
3183         // would cause all future lookups of this to be missing
3184         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3185         if (skinframe && skinframe->base)
3186                 return skinframe;
3187
3188         Image_StripImageExtension(name, basename, sizeof(basename));
3189
3190         // check for DDS texture file first
3191         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3192         {
3193                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3194                 if (basepixels == NULL)
3195                         return NULL;
3196         }
3197
3198         // FIXME handle miplevel
3199
3200         if (developer_loading.integer)
3201                 Con_Printf("loading skin \"%s\"\n", name);
3202
3203         // we've got some pixels to store, so really allocate this new texture now
3204         if (!skinframe)
3205                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3206         skinframe->stain = NULL;
3207         skinframe->merged = NULL;
3208         skinframe->base = NULL;
3209         skinframe->pants = NULL;
3210         skinframe->shirt = NULL;
3211         skinframe->nmap = NULL;
3212         skinframe->gloss = NULL;
3213         skinframe->glow = NULL;
3214         skinframe->fog = NULL;
3215         skinframe->reflect = NULL;
3216         skinframe->hasalpha = false;
3217
3218         if (ddsbase)
3219         {
3220                 skinframe->base = ddsbase;
3221                 skinframe->hasalpha = ddshasalpha;
3222                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3223                 if (r_loadfog && skinframe->hasalpha)
3224                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3225                 //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]);
3226         }
3227         else
3228         {
3229                 basepixels_width = image_width;
3230                 basepixels_height = image_height;
3231                 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);
3232                 if (textureflags & TEXF_ALPHA)
3233                 {
3234                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3235                         {
3236                                 if (basepixels[j] < 255)
3237                                 {
3238                                         skinframe->hasalpha = true;
3239                                         break;
3240                                 }
3241                         }
3242                         if (r_loadfog && skinframe->hasalpha)
3243                         {
3244                                 // has transparent pixels
3245                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3246                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3247                                 {
3248                                         pixels[j+0] = 255;
3249                                         pixels[j+1] = 255;
3250                                         pixels[j+2] = 255;
3251                                         pixels[j+3] = basepixels[j+3];
3252                                 }
3253                                 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);
3254                                 Mem_Free(pixels);
3255                         }
3256                 }
3257                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3258                 //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]);
3259                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3260                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3261                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3262                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3263         }
3264
3265         if (r_loaddds)
3266         {
3267                 mymiplevel = savemiplevel;
3268                 if (r_loadnormalmap)
3269                         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);
3270                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271                 if (r_loadgloss)
3272                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276         }
3277
3278         // _norm is the name used by tenebrae and has been adopted as standard
3279         if (r_loadnormalmap && skinframe->nmap == NULL)
3280         {
3281                 mymiplevel = savemiplevel;
3282                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283                 {
3284                         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);
3285                         Mem_Free(pixels);
3286                         pixels = NULL;
3287                 }
3288                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3289                 {
3290                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3291                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3292                         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);
3293                         Mem_Free(pixels);
3294                         Mem_Free(bumppixels);
3295                 }
3296                 else if (r_shadow_bumpscale_basetexture.value > 0)
3297                 {
3298                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3299                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3300                         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);
3301                         Mem_Free(pixels);
3302                 }
3303                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3304                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3305         }
3306
3307         // _luma is supported only for tenebrae compatibility
3308         // _glow is the preferred name
3309         mymiplevel = savemiplevel;
3310         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))))
3311         {
3312                 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);
3313                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3314                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3315                 Mem_Free(pixels);pixels = NULL;
3316         }
3317
3318         mymiplevel = savemiplevel;
3319         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3320         {
3321                 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);
3322                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3323                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3324                 Mem_Free(pixels);
3325                 pixels = NULL;
3326         }
3327
3328         mymiplevel = savemiplevel;
3329         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3330         {
3331                 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);
3332                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3333                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3334                 Mem_Free(pixels);
3335                 pixels = NULL;
3336         }
3337
3338         mymiplevel = savemiplevel;
3339         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3340         {
3341                 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);
3342                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3343                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3344                 Mem_Free(pixels);
3345                 pixels = NULL;
3346         }
3347
3348         mymiplevel = savemiplevel;
3349         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3350         {
3351                 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);
3352                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3353                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3354                 Mem_Free(pixels);
3355                 pixels = NULL;
3356         }
3357
3358         if (basepixels)
3359                 Mem_Free(basepixels);
3360
3361         return skinframe;
3362 }
3363
3364 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3365 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3366 {
3367         int i;
3368         unsigned char *temp1, *temp2;
3369         skinframe_t *skinframe;
3370
3371         if (cls.state == ca_dedicated)
3372                 return NULL;
3373
3374         // if already loaded just return it, otherwise make a new skinframe
3375         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3376         if (skinframe && skinframe->base)
3377                 return skinframe;
3378
3379         skinframe->stain = NULL;
3380         skinframe->merged = NULL;
3381         skinframe->base = NULL;
3382         skinframe->pants = NULL;
3383         skinframe->shirt = NULL;
3384         skinframe->nmap = NULL;
3385         skinframe->gloss = NULL;
3386         skinframe->glow = NULL;
3387         skinframe->fog = NULL;
3388         skinframe->reflect = NULL;
3389         skinframe->hasalpha = false;
3390
3391         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3392         if (!skindata)
3393                 return NULL;
3394
3395         if (developer_loading.integer)
3396                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3397
3398         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3399         {
3400                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3401                 temp2 = temp1 + width * height * 4;
3402                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3403                 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);
3404                 Mem_Free(temp1);
3405         }
3406         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3407         if (textureflags & TEXF_ALPHA)
3408         {
3409                 for (i = 3;i < width * height * 4;i += 4)
3410                 {
3411                         if (skindata[i] < 255)
3412                         {
3413                                 skinframe->hasalpha = true;
3414                                 break;
3415                         }
3416                 }
3417                 if (r_loadfog && skinframe->hasalpha)
3418                 {
3419                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3420                         memcpy(fogpixels, skindata, width * height * 4);
3421                         for (i = 0;i < width * height * 4;i += 4)
3422                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3423                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3424                         Mem_Free(fogpixels);
3425                 }
3426         }
3427
3428         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3429         //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]);
3430
3431         return skinframe;
3432 }
3433
3434 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3435 {
3436         int i;
3437         int featuresmask;
3438         skinframe_t *skinframe;
3439
3440         if (cls.state == ca_dedicated)
3441                 return NULL;
3442
3443         // if already loaded just return it, otherwise make a new skinframe
3444         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3445         if (skinframe && skinframe->base)
3446                 return skinframe;
3447
3448         skinframe->stain = NULL;
3449         skinframe->merged = NULL;
3450         skinframe->base = NULL;
3451         skinframe->pants = NULL;
3452         skinframe->shirt = NULL;
3453         skinframe->nmap = NULL;
3454         skinframe->gloss = NULL;
3455         skinframe->glow = NULL;
3456         skinframe->fog = NULL;
3457         skinframe->reflect = NULL;
3458         skinframe->hasalpha = false;
3459
3460         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3461         if (!skindata)
3462                 return NULL;
3463
3464         if (developer_loading.integer)
3465                 Con_Printf("loading quake skin \"%s\"\n", name);
3466
3467         // 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)
3468         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3469         memcpy(skinframe->qpixels, skindata, width*height);
3470         skinframe->qwidth = width;
3471         skinframe->qheight = height;
3472
3473         featuresmask = 0;
3474         for (i = 0;i < width * height;i++)
3475                 featuresmask |= palette_featureflags[skindata[i]];
3476
3477         skinframe->hasalpha = false;
3478         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3479         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3480         skinframe->qgeneratemerged = true;
3481         skinframe->qgeneratebase = skinframe->qhascolormapping;
3482         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3483
3484         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3485         //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]);
3486
3487         return skinframe;
3488 }
3489
3490 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3491 {
3492         int width;
3493         int height;
3494         unsigned char *skindata;
3495
3496         if (!skinframe->qpixels)
3497                 return;
3498
3499         if (!skinframe->qhascolormapping)
3500                 colormapped = false;
3501
3502         if (colormapped)
3503         {
3504                 if (!skinframe->qgeneratebase)
3505                         return;
3506         }
3507         else
3508         {
3509                 if (!skinframe->qgeneratemerged)
3510                         return;
3511         }
3512
3513         width = skinframe->qwidth;
3514         height = skinframe->qheight;
3515         skindata = skinframe->qpixels;
3516
3517         if (skinframe->qgeneratenmap)
3518         {
3519                 unsigned char *temp1, *temp2;
3520                 skinframe->qgeneratenmap = false;
3521                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522                 temp2 = temp1 + width * height * 4;
3523                 // use either a custom palette or the quake palette
3524                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3525                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526                 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);
3527                 Mem_Free(temp1);
3528         }
3529
3530         if (skinframe->qgenerateglow)
3531         {
3532                 skinframe->qgenerateglow = false;
3533                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3534         }
3535
3536         if (colormapped)
3537         {
3538                 skinframe->qgeneratebase = false;
3539                 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);
3540                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3541                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3542         }
3543         else
3544         {
3545                 skinframe->qgeneratemerged = false;
3546                 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);
3547         }
3548
3549         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3550         {
3551                 Mem_Free(skinframe->qpixels);
3552                 skinframe->qpixels = NULL;
3553         }
3554 }
3555
3556 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)
3557 {
3558         int i;
3559         skinframe_t *skinframe;
3560
3561         if (cls.state == ca_dedicated)
3562                 return NULL;
3563
3564         // if already loaded just return it, otherwise make a new skinframe
3565         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566         if (skinframe && skinframe->base)
3567                 return skinframe;
3568
3569         skinframe->stain = NULL;
3570         skinframe->merged = NULL;
3571         skinframe->base = NULL;
3572         skinframe->pants = NULL;
3573         skinframe->shirt = NULL;
3574         skinframe->nmap = NULL;
3575         skinframe->gloss = NULL;
3576         skinframe->glow = NULL;
3577         skinframe->fog = NULL;
3578         skinframe->reflect = NULL;
3579         skinframe->hasalpha = false;
3580
3581         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3582         if (!skindata)
3583                 return NULL;
3584
3585         if (developer_loading.integer)
3586                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3587
3588         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3589         if (textureflags & TEXF_ALPHA)
3590         {
3591                 for (i = 0;i < width * height;i++)
3592                 {
3593                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3594                         {
3595                                 skinframe->hasalpha = true;
3596                                 break;
3597                         }
3598                 }
3599                 if (r_loadfog && skinframe->hasalpha)
3600                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3601         }
3602
3603         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3604         //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]);
3605
3606         return skinframe;
3607 }
3608
3609 skinframe_t *R_SkinFrame_LoadMissing(void)
3610 {
3611         skinframe_t *skinframe;
3612
3613         if (cls.state == ca_dedicated)
3614                 return NULL;
3615
3616         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3617         skinframe->stain = NULL;
3618         skinframe->merged = NULL;
3619         skinframe->base = NULL;
3620         skinframe->pants = NULL;
3621         skinframe->shirt = NULL;
3622         skinframe->nmap = NULL;
3623         skinframe->gloss = NULL;
3624         skinframe->glow = NULL;
3625         skinframe->fog = NULL;
3626         skinframe->reflect = NULL;
3627         skinframe->hasalpha = false;
3628
3629         skinframe->avgcolor[0] = rand() / RAND_MAX;
3630         skinframe->avgcolor[1] = rand() / RAND_MAX;
3631         skinframe->avgcolor[2] = rand() / RAND_MAX;
3632         skinframe->avgcolor[3] = 1;
3633
3634         return skinframe;
3635 }
3636
3637 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3638 typedef struct suffixinfo_s
3639 {
3640         const char *suffix;
3641         qboolean flipx, flipy, flipdiagonal;
3642 }
3643 suffixinfo_t;
3644 static suffixinfo_t suffix[3][6] =
3645 {
3646         {
3647                 {"px",   false, false, false},
3648                 {"nx",   false, false, false},
3649                 {"py",   false, false, false},
3650                 {"ny",   false, false, false},
3651                 {"pz",   false, false, false},
3652                 {"nz",   false, false, false}
3653         },
3654         {
3655                 {"posx", false, false, false},
3656                 {"negx", false, false, false},
3657                 {"posy", false, false, false},
3658                 {"negy", false, false, false},
3659                 {"posz", false, false, false},
3660                 {"negz", false, false, false}
3661         },
3662         {
3663                 {"rt",    true, false,  true},
3664                 {"lf",   false,  true,  true},
3665                 {"ft",    true,  true, false},
3666                 {"bk",   false, false, false},
3667                 {"up",    true, false,  true},
3668                 {"dn",    true, false,  true}
3669         }
3670 };
3671
3672 static int componentorder[4] = {0, 1, 2, 3};
3673
3674 rtexture_t *R_LoadCubemap(const char *basename)
3675 {
3676         int i, j, cubemapsize;
3677         unsigned char *cubemappixels, *image_buffer;
3678         rtexture_t *cubemaptexture;
3679         char name[256];
3680         // must start 0 so the first loadimagepixels has no requested width/height
3681         cubemapsize = 0;
3682         cubemappixels = NULL;
3683         cubemaptexture = NULL;
3684         // keep trying different suffix groups (posx, px, rt) until one loads
3685         for (j = 0;j < 3 && !cubemappixels;j++)
3686         {
3687                 // load the 6 images in the suffix group
3688                 for (i = 0;i < 6;i++)
3689                 {
3690                         // generate an image name based on the base and and suffix
3691                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3692                         // load it
3693                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3694                         {
3695                                 // an image loaded, make sure width and height are equal
3696                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3697                                 {
3698                                         // if this is the first image to load successfully, allocate the cubemap memory
3699                                         if (!cubemappixels && image_width >= 1)
3700                                         {
3701                                                 cubemapsize = image_width;
3702                                                 // note this clears to black, so unavailable sides are black
3703                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3704                                         }
3705                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3706                                         if (cubemappixels)
3707                                                 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);
3708                                 }
3709                                 else
3710                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3711                                 // free the image
3712                                 Mem_Free(image_buffer);
3713                         }
3714                 }
3715         }
3716         // if a cubemap loaded, upload it
3717         if (cubemappixels)
3718         {
3719                 if (developer_loading.integer)
3720                         Con_Printf("loading cubemap \"%s\"\n", basename);
3721
3722                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3723                 Mem_Free(cubemappixels);
3724         }
3725         else
3726         {
3727                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3728                 if (developer_loading.integer)
3729                 {
3730                         Con_Printf("(tried tried images ");
3731                         for (j = 0;j < 3;j++)
3732                                 for (i = 0;i < 6;i++)
3733                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3734                         Con_Print(" and was unable to find any of them).\n");
3735                 }
3736         }
3737         return cubemaptexture;
3738 }
3739
3740 rtexture_t *R_GetCubemap(const char *basename)
3741 {
3742         int i;
3743         for (i = 0;i < r_texture_numcubemaps;i++)
3744                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3745                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3746         if (i >= MAX_CUBEMAPS)
3747                 return r_texture_whitecube;
3748         r_texture_numcubemaps++;
3749         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3750         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3751         return r_texture_cubemaps[i].texture;
3752 }
3753
3754 void R_FreeCubemaps(void)
3755 {
3756         int i;
3757         for (i = 0;i < r_texture_numcubemaps;i++)
3758         {
3759                 if (developer_loading.integer)
3760                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3761                 if (r_texture_cubemaps[i].texture)
3762                         R_FreeTexture(r_texture_cubemaps[i].texture);
3763         }
3764         r_texture_numcubemaps = 0;
3765 }
3766
3767 void R_Main_FreeViewCache(void)
3768 {
3769         if (r_refdef.viewcache.entityvisible)
3770                 Mem_Free(r_refdef.viewcache.entityvisible);
3771         if (r_refdef.viewcache.world_pvsbits)
3772                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3773         if (r_refdef.viewcache.world_leafvisible)
3774                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3775         if (r_refdef.viewcache.world_surfacevisible)
3776                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3777         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3778 }
3779
3780 void R_Main_ResizeViewCache(void)
3781 {
3782         int numentities = r_refdef.scene.numentities;
3783         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3784         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3785         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3786         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3787         if (r_refdef.viewcache.maxentities < numentities)
3788         {
3789                 r_refdef.viewcache.maxentities = numentities;
3790                 if (r_refdef.viewcache.entityvisible)
3791                         Mem_Free(r_refdef.viewcache.entityvisible);
3792                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3793         }
3794         if (r_refdef.viewcache.world_numclusters != numclusters)
3795         {
3796                 r_refdef.viewcache.world_numclusters = numclusters;
3797                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3798                 if (r_refdef.viewcache.world_pvsbits)
3799                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3800                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3801         }
3802         if (r_refdef.viewcache.world_numleafs != numleafs)
3803         {
3804                 r_refdef.viewcache.world_numleafs = numleafs;
3805                 if (r_refdef.viewcache.world_leafvisible)
3806                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3807                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3808         }
3809         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3810         {
3811                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3812                 if (r_refdef.viewcache.world_surfacevisible)
3813                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3814                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3815         }
3816 }
3817
3818 extern rtexture_t *loadingscreentexture;
3819 void gl_main_start(void)
3820 {
3821         loadingscreentexture = NULL;
3822         r_texture_blanknormalmap = NULL;
3823         r_texture_white = NULL;
3824         r_texture_grey128 = NULL;
3825         r_texture_black = NULL;
3826         r_texture_whitecube = NULL;
3827         r_texture_normalizationcube = NULL;
3828         r_texture_fogattenuation = NULL;
3829         r_texture_fogheighttexture = NULL;
3830         r_texture_gammaramps = NULL;
3831         r_texture_numcubemaps = 0;
3832
3833         r_loaddds = r_texture_dds_load.integer != 0;
3834         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3835
3836         switch(vid.renderpath)
3837         {
3838         case RENDERPATH_GL20:
3839         case RENDERPATH_D3D9:
3840         case RENDERPATH_D3D10:
3841         case RENDERPATH_D3D11:
3842         case RENDERPATH_SOFT:
3843                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3844                 Cvar_SetValueQuick(&gl_combine, 1);
3845                 Cvar_SetValueQuick(&r_glsl, 1);
3846                 r_loadnormalmap = true;
3847                 r_loadgloss = true;
3848                 r_loadfog = false;
3849                 break;
3850         case RENDERPATH_GL13:
3851                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3852                 Cvar_SetValueQuick(&gl_combine, 1);
3853                 Cvar_SetValueQuick(&r_glsl, 0);
3854                 r_loadnormalmap = false;
3855                 r_loadgloss = false;
3856                 r_loadfog = true;
3857                 break;
3858         case RENDERPATH_GL11:
3859                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3860                 Cvar_SetValueQuick(&gl_combine, 0);
3861                 Cvar_SetValueQuick(&r_glsl, 0);
3862                 r_loadnormalmap = false;
3863                 r_loadgloss = false;
3864                 r_loadfog = true;
3865                 break;
3866         case RENDERPATH_GLES2:
3867                 Cvar_SetValueQuick(&r_textureunits, 1);
3868                 Cvar_SetValueQuick(&gl_combine, 1);
3869                 Cvar_SetValueQuick(&r_glsl, 1);
3870                 r_loadnormalmap = true;
3871                 r_loadgloss = false;
3872                 r_loadfog = false;
3873                 break;
3874         }
3875
3876         R_AnimCache_Free();
3877         R_FrameData_Reset();
3878
3879         r_numqueries = 0;
3880         r_maxqueries = 0;
3881         memset(r_queries, 0, sizeof(r_queries));
3882
3883         r_qwskincache = NULL;
3884         r_qwskincache_size = 0;
3885
3886         // due to caching of texture_t references, the collision cache must be reset
3887         Collision_Cache_Reset(true);
3888
3889         // set up r_skinframe loading system for textures
3890         memset(&r_skinframe, 0, sizeof(r_skinframe));
3891         r_skinframe.loadsequence = 1;
3892         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3893
3894         r_main_texturepool = R_AllocTexturePool();
3895         R_BuildBlankTextures();
3896         R_BuildNoTexture();
3897         if (vid.support.arb_texture_cube_map)
3898         {
3899                 R_BuildWhiteCube();
3900                 R_BuildNormalizationCube();
3901         }
3902         r_texture_fogattenuation = NULL;
3903         r_texture_fogheighttexture = NULL;
3904         r_texture_gammaramps = NULL;
3905         //r_texture_fogintensity = NULL;
3906         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3907         memset(&r_waterstate, 0, sizeof(r_waterstate));
3908         r_glsl_permutation = NULL;
3909         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3910         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3911         glslshaderstring = NULL;
3912 #ifdef SUPPORTD3D
3913         r_hlsl_permutation = NULL;
3914         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3915         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3916 #endif
3917         hlslshaderstring = NULL;
3918         memset(&r_svbsp, 0, sizeof (r_svbsp));
3919
3920         r_refdef.fogmasktable_density = 0;
3921 }
3922
3923 void gl_main_shutdown(void)
3924 {
3925         R_AnimCache_Free();
3926         R_FrameData_Reset();
3927
3928         R_Main_FreeViewCache();
3929
3930         switch(vid.renderpath)
3931         {
3932         case RENDERPATH_GL11:
3933         case RENDERPATH_GL13:
3934         case RENDERPATH_GL20:
3935         case RENDERPATH_GLES2:
3936                 if (r_maxqueries)
3937                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3938                 break;
3939         case RENDERPATH_D3D9:
3940                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3941                 break;
3942         case RENDERPATH_D3D10:
3943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3944                 break;
3945         case RENDERPATH_D3D11:
3946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3947                 break;
3948         case RENDERPATH_SOFT:
3949                 break;
3950         }
3951
3952         r_numqueries = 0;
3953         r_maxqueries = 0;
3954         memset(r_queries, 0, sizeof(r_queries));
3955
3956         r_qwskincache = NULL;
3957         r_qwskincache_size = 0;
3958
3959         // clear out the r_skinframe state
3960         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3961         memset(&r_skinframe, 0, sizeof(r_skinframe));
3962
3963         if (r_svbsp.nodes)
3964                 Mem_Free(r_svbsp.nodes);
3965         memset(&r_svbsp, 0, sizeof (r_svbsp));
3966         R_FreeTexturePool(&r_main_texturepool);
3967         loadingscreentexture = NULL;
3968         r_texture_blanknormalmap = NULL;
3969         r_texture_white = NULL;
3970         r_texture_grey128 = NULL;
3971         r_texture_black = NULL;
3972         r_texture_whitecube = NULL;
3973         r_texture_normalizationcube = NULL;
3974         r_texture_fogattenuation = NULL;
3975         r_texture_fogheighttexture = NULL;
3976         r_texture_gammaramps = NULL;
3977         r_texture_numcubemaps = 0;
3978         //r_texture_fogintensity = NULL;
3979         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3980         memset(&r_waterstate, 0, sizeof(r_waterstate));
3981         R_GLSL_Restart_f();
3982
3983         r_glsl_permutation = NULL;
3984         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3985         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3986         glslshaderstring = NULL;
3987 #ifdef SUPPORTD3D
3988         r_hlsl_permutation = NULL;
3989         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3990         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3991 #endif
3992         hlslshaderstring = NULL;
3993 }
3994
3995 extern void CL_ParseEntityLump(char *entitystring);
3996 void gl_main_newmap(void)
3997 {
3998         // FIXME: move this code to client
3999         char *entities, entname[MAX_QPATH];
4000         if (r_qwskincache)
4001                 Mem_Free(r_qwskincache);
4002         r_qwskincache = NULL;
4003         r_qwskincache_size = 0;
4004         if (cl.worldmodel)
4005         {
4006                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4007                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4008                 {
4009                         CL_ParseEntityLump(entities);
4010                         Mem_Free(entities);
4011                         return;
4012                 }
4013                 if (cl.worldmodel->brush.entities)
4014                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4015         }
4016         R_Main_FreeViewCache();
4017
4018         R_FrameData_Reset();
4019 }
4020
4021 void GL_Main_Init(void)
4022 {
4023         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4024
4025         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4026         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4027         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4028         if (gamemode == GAME_NEHAHRA)
4029         {
4030                 Cvar_RegisterVariable (&gl_fogenable);
4031                 Cvar_RegisterVariable (&gl_fogdensity);
4032                 Cvar_RegisterVariable (&gl_fogred);
4033                 Cvar_RegisterVariable (&gl_foggreen);
4034                 Cvar_RegisterVariable (&gl_fogblue);
4035                 Cvar_RegisterVariable (&gl_fogstart);
4036                 Cvar_RegisterVariable (&gl_fogend);
4037                 Cvar_RegisterVariable (&gl_skyclip);
4038         }
4039         Cvar_RegisterVariable(&r_motionblur);
4040         Cvar_RegisterVariable(&r_motionblur_maxblur);
4041         Cvar_RegisterVariable(&r_motionblur_bmin);
4042         Cvar_RegisterVariable(&r_motionblur_vmin);
4043         Cvar_RegisterVariable(&r_motionblur_vmax);
4044         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4045         Cvar_RegisterVariable(&r_motionblur_randomize);
4046         Cvar_RegisterVariable(&r_damageblur);
4047         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4048         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4049         Cvar_RegisterVariable(&r_equalize_entities_by);
4050         Cvar_RegisterVariable(&r_equalize_entities_to);
4051         Cvar_RegisterVariable(&r_depthfirst);
4052         Cvar_RegisterVariable(&r_useinfinitefarclip);
4053         Cvar_RegisterVariable(&r_farclip_base);
4054         Cvar_RegisterVariable(&r_farclip_world);
4055         Cvar_RegisterVariable(&r_nearclip);
4056         Cvar_RegisterVariable(&r_showbboxes);
4057         Cvar_RegisterVariable(&r_showsurfaces);
4058         Cvar_RegisterVariable(&r_showtris);
4059         Cvar_RegisterVariable(&r_shownormals);
4060         Cvar_RegisterVariable(&r_showlighting);
4061         Cvar_RegisterVariable(&r_showshadowvolumes);
4062         Cvar_RegisterVariable(&r_showcollisionbrushes);
4063         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4064         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4065         Cvar_RegisterVariable(&r_showdisabledepthtest);
4066         Cvar_RegisterVariable(&r_drawportals);
4067         Cvar_RegisterVariable(&r_drawentities);
4068         Cvar_RegisterVariable(&r_draw2d);
4069         Cvar_RegisterVariable(&r_drawworld);
4070         Cvar_RegisterVariable(&r_cullentities_trace);
4071         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4072         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4073         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4074         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4075         Cvar_RegisterVariable(&r_drawviewmodel);
4076         Cvar_RegisterVariable(&r_drawexteriormodel);
4077         Cvar_RegisterVariable(&r_speeds);
4078         Cvar_RegisterVariable(&r_fullbrights);
4079         Cvar_RegisterVariable(&r_wateralpha);
4080         Cvar_RegisterVariable(&r_dynamic);
4081         Cvar_RegisterVariable(&r_fakelight);
4082         Cvar_RegisterVariable(&r_fakelight_intensity);
4083         Cvar_RegisterVariable(&r_fullbright);
4084         Cvar_RegisterVariable(&r_shadows);
4085         Cvar_RegisterVariable(&r_shadows_darken);
4086         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4087         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4088         Cvar_RegisterVariable(&r_shadows_throwdistance);
4089         Cvar_RegisterVariable(&r_shadows_throwdirection);
4090         Cvar_RegisterVariable(&r_shadows_focus);
4091         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4092         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4093         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4094         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4095         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4096         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4097         Cvar_RegisterVariable(&r_fog_exp2);
4098         Cvar_RegisterVariable(&r_fog_clear);
4099         Cvar_RegisterVariable(&r_drawfog);
4100         Cvar_RegisterVariable(&r_transparentdepthmasking);
4101         Cvar_RegisterVariable(&r_texture_dds_load);
4102         Cvar_RegisterVariable(&r_texture_dds_save);
4103         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4104         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4105         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4106         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4107         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4108         Cvar_RegisterVariable(&r_textureunits);
4109         Cvar_RegisterVariable(&gl_combine);
4110         Cvar_RegisterVariable(&r_viewfbo);
4111         Cvar_RegisterVariable(&r_viewscale);
4112         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4113         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4114         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4115         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4116         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4117         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4118         Cvar_RegisterVariable(&r_glsl);
4119         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4120         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4121         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4122         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4123         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4124         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4125         Cvar_RegisterVariable(&r_glsl_postprocess);
4126         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4127         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4128         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4129         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4130         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4131         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4132         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4133         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4134
4135         Cvar_RegisterVariable(&r_water);
4136         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4137         Cvar_RegisterVariable(&r_water_clippingplanebias);
4138         Cvar_RegisterVariable(&r_water_refractdistort);
4139         Cvar_RegisterVariable(&r_water_reflectdistort);
4140         Cvar_RegisterVariable(&r_water_scissormode);
4141         Cvar_RegisterVariable(&r_lerpsprites);
4142         Cvar_RegisterVariable(&r_lerpmodels);
4143         Cvar_RegisterVariable(&r_lerplightstyles);
4144         Cvar_RegisterVariable(&r_waterscroll);
4145         Cvar_RegisterVariable(&r_bloom);
4146         Cvar_RegisterVariable(&r_bloom_colorscale);
4147         Cvar_RegisterVariable(&r_bloom_brighten);
4148         Cvar_RegisterVariable(&r_bloom_blur);
4149         Cvar_RegisterVariable(&r_bloom_resolution);
4150         Cvar_RegisterVariable(&r_bloom_colorexponent);
4151         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4152         Cvar_RegisterVariable(&r_hdr);
4153         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4154         Cvar_RegisterVariable(&r_hdr_glowintensity);
4155         Cvar_RegisterVariable(&r_hdr_range);
4156         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4157         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4158         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4159         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4160         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4161         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4162         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4163         Cvar_RegisterVariable(&developer_texturelogging);
4164         Cvar_RegisterVariable(&gl_lightmaps);
4165         Cvar_RegisterVariable(&r_test);
4166         Cvar_RegisterVariable(&r_glsl_saturation);
4167         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4168         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4169         Cvar_RegisterVariable(&r_framedatasize);
4170         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4171                 Cvar_SetValue("r_fullbrights", 0);
4172         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4173
4174         Cvar_RegisterVariable(&r_track_sprites);
4175         Cvar_RegisterVariable(&r_track_sprites_flags);
4176         Cvar_RegisterVariable(&r_track_sprites_scalew);
4177         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4178         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4179         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4180         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4181         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4182 }
4183
4184 extern void R_Textures_Init(void);
4185 extern void GL_Draw_Init(void);
4186 extern void GL_Main_Init(void);
4187 extern void R_Shadow_Init(void);
4188 extern void R_Sky_Init(void);
4189 extern void GL_Surf_Init(void);
4190 extern void R_Particles_Init(void);
4191 extern void R_Explosion_Init(void);
4192 extern void gl_backend_init(void);
4193 extern void Sbar_Init(void);
4194 extern void R_LightningBeams_Init(void);
4195 extern void Mod_RenderInit(void);
4196 extern void Font_Init(void);
4197
4198 void Render_Init(void)
4199 {
4200         gl_backend_init();
4201         R_Textures_Init();
4202         GL_Main_Init();
4203         Font_Init();
4204         GL_Draw_Init();
4205         R_Shadow_Init();
4206         R_Sky_Init();
4207         GL_Surf_Init();
4208         Sbar_Init();
4209         R_Particles_Init();
4210         R_Explosion_Init();
4211         R_LightningBeams_Init();
4212         Mod_RenderInit();
4213 }
4214
4215 /*
4216 ===============
4217 GL_Init
4218 ===============
4219 */
4220 extern char *ENGINE_EXTENSIONS;
4221 void GL_Init (void)
4222 {
4223         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4224         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4225         gl_version = (const char *)qglGetString(GL_VERSION);
4226         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4227
4228         if (!gl_extensions)
4229                 gl_extensions = "";
4230         if (!gl_platformextensions)
4231                 gl_platformextensions = "";
4232
4233         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4234         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4235         Con_Printf("GL_VERSION: %s\n", gl_version);
4236         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4237         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4238
4239         VID_CheckExtensions();
4240
4241         // LordHavoc: report supported extensions
4242         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4243
4244         // clear to black (loading plaque will be seen over this)
4245         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4246 }
4247
4248 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4249 {
4250         int i;
4251         mplane_t *p;
4252         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4253         {
4254                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4255                 if (i == 4)
4256                         continue;
4257                 p = r_refdef.view.frustum + i;
4258                 switch(p->signbits)
4259                 {
4260                 default:
4261                 case 0:
4262                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4263                                 return true;
4264                         break;
4265                 case 1:
4266                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4267                                 return true;
4268                         break;
4269                 case 2:
4270                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4271                                 return true;
4272                         break;
4273                 case 3:
4274                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4275                                 return true;
4276                         break;
4277                 case 4:
4278                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4279                                 return true;
4280                         break;
4281                 case 5:
4282                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4283                                 return true;
4284                         break;
4285                 case 6:
4286                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4287                                 return true;
4288                         break;
4289                 case 7:
4290                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4291                                 return true;
4292                         break;
4293                 }
4294         }
4295         return false;
4296 }
4297
4298 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4299 {
4300         int i;
4301         const mplane_t *p;
4302         for (i = 0;i < numplanes;i++)
4303         {
4304                 p = planes + i;
4305                 switch(p->signbits)
4306                 {
4307                 default:
4308                 case 0:
4309                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4310                                 return true;
4311                         break;
4312                 case 1:
4313                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4314                                 return true;
4315                         break;
4316                 case 2:
4317                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4318                                 return true;
4319                         break;
4320                 case 3:
4321                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4322                                 return true;
4323                         break;
4324                 case 4:
4325                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4326                                 return true;
4327                         break;
4328                 case 5:
4329                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4330                                 return true;
4331                         break;
4332                 case 6:
4333                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4334                                 return true;
4335                         break;
4336                 case 7:
4337                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4338                                 return true;
4339                         break;
4340                 }
4341         }
4342         return false;
4343 }
4344
4345 //==================================================================================
4346
4347 // LordHavoc: this stores temporary data used within the same frame
4348
4349 typedef struct r_framedata_mem_s
4350 {
4351         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4352         size_t size; // how much usable space
4353         size_t current; // how much space in use
4354         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4355         size_t wantedsize; // how much space was allocated
4356         unsigned char *data; // start of real data (16byte aligned)
4357 }
4358 r_framedata_mem_t;
4359
4360 static r_framedata_mem_t *r_framedata_mem;
4361
4362 void R_FrameData_Reset(void)
4363 {
4364         while (r_framedata_mem)
4365         {
4366                 r_framedata_mem_t *next = r_framedata_mem->purge;
4367                 Mem_Free(r_framedata_mem);
4368                 r_framedata_mem = next;
4369         }
4370 }
4371
4372 void R_FrameData_Resize(void)
4373 {
4374         size_t wantedsize;
4375         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4376         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4377         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4378         {
4379                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4380                 newmem->wantedsize = wantedsize;
4381                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4382                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4383                 newmem->current = 0;
4384                 newmem->mark = 0;
4385                 newmem->purge = r_framedata_mem;
4386                 r_framedata_mem = newmem;
4387         }
4388 }
4389
4390 void R_FrameData_NewFrame(void)
4391 {
4392         R_FrameData_Resize();
4393         if (!r_framedata_mem)
4394                 return;
4395         // if we ran out of space on the last frame, free the old memory now
4396         while (r_framedata_mem->purge)
4397         {
4398                 // repeatedly remove the second item in the list, leaving only head
4399                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4400                 Mem_Free(r_framedata_mem->purge);
4401                 r_framedata_mem->purge = next;
4402         }
4403         // reset the current mem pointer
4404         r_framedata_mem->current = 0;
4405         r_framedata_mem->mark = 0;
4406 }
4407
4408 void *R_FrameData_Alloc(size_t size)
4409 {
4410         void *data;
4411
4412         // align to 16 byte boundary - the data pointer is already aligned, so we
4413         // only need to ensure the size of every allocation is also aligned
4414         size = (size + 15) & ~15;
4415
4416         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4417         {
4418                 // emergency - we ran out of space, allocate more memory
4419                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4420                 R_FrameData_Resize();
4421         }
4422
4423         data = r_framedata_mem->data + r_framedata_mem->current;
4424         r_framedata_mem->current += size;
4425
4426         // count the usage for stats
4427         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4428         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4429
4430         return (void *)data;
4431 }
4432
4433 void *R_FrameData_Store(size_t size, void *data)
4434 {
4435         void *d = R_FrameData_Alloc(size);
4436         if (d && data)
4437                 memcpy(d, data, size);
4438         return d;
4439 }
4440
4441 void R_FrameData_SetMark(void)
4442 {
4443         if (!r_framedata_mem)
4444                 return;
4445         r_framedata_mem->mark = r_framedata_mem->current;
4446 }
4447
4448 void R_FrameData_ReturnToMark(void)
4449 {
4450         if (!r_framedata_mem)
4451                 return;
4452         r_framedata_mem->current = r_framedata_mem->mark;
4453 }
4454
4455 //==================================================================================
4456
4457 // LordHavoc: animcache originally written by Echon, rewritten since then
4458
4459 /**
4460  * Animation cache prevents re-generating mesh data for an animated model
4461  * multiple times in one frame for lighting, shadowing, reflections, etc.
4462  */
4463
4464 void R_AnimCache_Free(void)
4465 {
4466 }
4467
4468 void R_AnimCache_ClearCache(void)
4469 {
4470         int i;
4471         entity_render_t *ent;
4472
4473         for (i = 0;i < r_refdef.scene.numentities;i++)
4474         {
4475                 ent = r_refdef.scene.entities[i];
4476                 ent->animcache_vertex3f = NULL;
4477                 ent->animcache_normal3f = NULL;
4478                 ent->animcache_svector3f = NULL;
4479                 ent->animcache_tvector3f = NULL;
4480                 ent->animcache_vertexmesh = NULL;
4481                 ent->animcache_vertex3fbuffer = NULL;
4482                 ent->animcache_vertexmeshbuffer = NULL;
4483         }
4484 }
4485
4486 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4487 {
4488         int i;
4489
4490         // check if we need the meshbuffers
4491         if (!vid.useinterleavedarrays)
4492                 return;
4493
4494         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4495                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4496         // TODO: upload vertex3f buffer?
4497         if (ent->animcache_vertexmesh)
4498         {
4499                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4500                 for (i = 0;i < numvertices;i++)
4501                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4502                 if (ent->animcache_svector3f)
4503                         for (i = 0;i < numvertices;i++)
4504                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4505                 if (ent->animcache_tvector3f)
4506                         for (i = 0;i < numvertices;i++)
4507                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4508                 if (ent->animcache_normal3f)
4509                         for (i = 0;i < numvertices;i++)
4510                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4511                 // TODO: upload vertexmeshbuffer?
4512         }
4513 }
4514
4515 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4516 {
4517         dp_model_t *model = ent->model;
4518         int numvertices;
4519         // see if it's already cached this frame
4520         if (ent->animcache_vertex3f)
4521         {
4522                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4523                 if (wantnormals || wanttangents)
4524                 {
4525                         if (ent->animcache_normal3f)
4526                                 wantnormals = false;
4527                         if (ent->animcache_svector3f)
4528                                 wanttangents = false;
4529                         if (wantnormals || wanttangents)
4530                         {
4531                                 numvertices = model->surfmesh.num_vertices;
4532                                 if (wantnormals)
4533                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4534                                 if (wanttangents)
4535                                 {
4536                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4537                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4538                                 }
4539                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4540                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4541                         }
4542                 }
4543         }
4544         else
4545         {
4546                 // see if this ent is worth caching
4547                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4548                         return false;
4549                 // get some memory for this entity and generate mesh data
4550                 numvertices = model->surfmesh.num_vertices;
4551                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4552                 if (wantnormals)
4553                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4554                 if (wanttangents)
4555                 {
4556                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4557                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4558                 }
4559                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4560                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4561         }
4562         return true;
4563 }
4564
4565 void R_AnimCache_CacheVisibleEntities(void)
4566 {
4567         int i;
4568         qboolean wantnormals = true;
4569         qboolean wanttangents = !r_showsurfaces.integer;
4570
4571         switch(vid.renderpath)
4572         {
4573         case RENDERPATH_GL20:
4574         case RENDERPATH_D3D9:
4575         case RENDERPATH_D3D10:
4576         case RENDERPATH_D3D11:
4577         case RENDERPATH_GLES2:
4578                 break;
4579         case RENDERPATH_GL13:
4580         case RENDERPATH_GL11:
4581                 wanttangents = false;
4582                 break;
4583         case RENDERPATH_SOFT:
4584                 break;
4585         }
4586
4587         if (r_shownormals.integer)
4588                 wanttangents = wantnormals = true;
4589
4590         // TODO: thread this
4591         // NOTE: R_PrepareRTLights() also caches entities
4592
4593         for (i = 0;i < r_refdef.scene.numentities;i++)
4594                 if (r_refdef.viewcache.entityvisible[i])
4595                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4596 }
4597
4598 //==================================================================================
4599
4600 static void R_View_UpdateEntityLighting (void)
4601 {
4602         int i;
4603         entity_render_t *ent;
4604         vec3_t tempdiffusenormal, avg;
4605         vec_t f, fa, fd, fdd;
4606         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4607
4608         for (i = 0;i < r_refdef.scene.numentities;i++)
4609         {
4610                 ent = r_refdef.scene.entities[i];
4611
4612                 // skip unseen models
4613                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4614                         continue;
4615
4616                 // skip bsp models
4617                 if (ent->model && ent->model->brush.num_leafs)
4618                 {
4619                         // TODO: use modellight for r_ambient settings on world?
4620                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4621                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4622                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4623                         continue;
4624                 }
4625
4626                 // fetch the lighting from the worldmodel data
4627                 VectorClear(ent->modellight_ambient);
4628                 VectorClear(ent->modellight_diffuse);
4629                 VectorClear(tempdiffusenormal);
4630                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4631                 {
4632                         vec3_t org;
4633                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4634
4635                         // complete lightning for lit sprites
4636                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4637                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4638                         {
4639                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4640                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4641                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4642                         }
4643                         else
4644                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4645
4646                         if(ent->flags & RENDER_EQUALIZE)
4647                         {
4648                                 // first fix up ambient lighting...
4649                                 if(r_equalize_entities_minambient.value > 0)
4650                                 {
4651                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4652                                         if(fd > 0)
4653                                         {
4654                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4655                                                 if(fa < r_equalize_entities_minambient.value * fd)
4656                                                 {
4657                                                         // solve:
4658                                                         //   fa'/fd' = minambient
4659                                                         //   fa'+0.25*fd' = fa+0.25*fd
4660                                                         //   ...
4661                                                         //   fa' = fd' * minambient
4662                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4663                                                         //   ...
4664                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4665                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4666                                                         //   ...
4667                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4668                                                         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
4669                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4670                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4671                                                 }
4672                                         }
4673                                 }
4674
4675                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4676                                 {
4677                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4678                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4679                                         f = fa + 0.25 * fd;
4680                                         if(f > 0)
4681                                         {
4682                                                 // adjust brightness and saturation to target
4683                                                 avg[0] = avg[1] = avg[2] = fa / f;
4684                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4685                                                 avg[0] = avg[1] = avg[2] = fd / f;
4686                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4687                                         }
4688                                 }
4689                         }
4690                 }
4691                 else // highly rare
4692                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4693
4694                 // move the light direction into modelspace coordinates for lighting code
4695                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4696                 if(VectorLength2(ent->modellight_lightdir) == 0)
4697                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4698                 VectorNormalize(ent->modellight_lightdir);
4699         }
4700 }
4701
4702 #define MAX_LINEOFSIGHTTRACES 64
4703
4704 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4705 {
4706         int i;
4707         vec3_t boxmins, boxmaxs;
4708         vec3_t start;
4709         vec3_t end;
4710         dp_model_t *model = r_refdef.scene.worldmodel;
4711
4712         if (!model || !model->brush.TraceLineOfSight)
4713                 return true;
4714
4715         // expand the box a little
4716         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4717         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4718         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4719         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4720         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4721         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4722
4723         // return true if eye is inside enlarged box
4724         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4725                 return true;
4726
4727         // try center
4728         VectorCopy(eye, start);
4729         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4730         if (model->brush.TraceLineOfSight(model, start, end))
4731                 return true;
4732
4733         // try various random positions
4734         for (i = 0;i < numsamples;i++)
4735         {
4736                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4737                 if (model->brush.TraceLineOfSight(model, start, end))
4738                         return true;
4739         }
4740
4741         return false;
4742 }
4743
4744
4745 static void R_View_UpdateEntityVisible (void)
4746 {
4747         int i;
4748         int renderimask;
4749         int samples;
4750         entity_render_t *ent;
4751
4752         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4753                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4754                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4755                 :                                                          RENDER_EXTERIORMODEL;
4756         if (!r_drawviewmodel.integer)
4757                 renderimask |= RENDER_VIEWMODEL;
4758         if (!r_drawexteriormodel.integer)
4759                 renderimask |= RENDER_EXTERIORMODEL;
4760         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4761         {
4762                 // worldmodel can check visibility
4763                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4764                 for (i = 0;i < r_refdef.scene.numentities;i++)
4765                 {
4766                         ent = r_refdef.scene.entities[i];
4767                         if (!(ent->flags & renderimask))
4768                         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)))
4769                         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))
4770                                 r_refdef.viewcache.entityvisible[i] = true;
4771                 }
4772                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4773                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4774                 {
4775                         for (i = 0;i < r_refdef.scene.numentities;i++)
4776                         {
4777                                 ent = r_refdef.scene.entities[i];
4778                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4779                                 {
4780                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4781                                         if (samples < 0)
4782                                                 continue; // temp entities do pvs only
4783                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4784                                                 ent->last_trace_visibility = realtime;
4785                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4786                                                 r_refdef.viewcache.entityvisible[i] = 0;
4787                                 }
4788                         }
4789                 }
4790         }
4791         else
4792         {
4793                 // no worldmodel or it can't check visibility
4794                 for (i = 0;i < r_refdef.scene.numentities;i++)
4795                 {
4796                         ent = r_refdef.scene.entities[i];
4797                         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));
4798                 }
4799         }
4800 }
4801
4802 /// only used if skyrendermasked, and normally returns false
4803 int R_DrawBrushModelsSky (void)
4804 {
4805         int i, sky;
4806         entity_render_t *ent;
4807
4808         sky = false;
4809         for (i = 0;i < r_refdef.scene.numentities;i++)
4810         {
4811                 if (!r_refdef.viewcache.entityvisible[i])
4812                         continue;
4813                 ent = r_refdef.scene.entities[i];
4814                 if (!ent->model || !ent->model->DrawSky)
4815                         continue;
4816                 ent->model->DrawSky(ent);
4817                 sky = true;
4818         }
4819         return sky;
4820 }
4821
4822 static void R_DrawNoModel(entity_render_t *ent);
4823 static void R_DrawModels(void)
4824 {
4825         int i;
4826         entity_render_t *ent;
4827
4828         for (i = 0;i < r_refdef.scene.numentities;i++)
4829         {
4830                 if (!r_refdef.viewcache.entityvisible[i])
4831                         continue;
4832                 ent = r_refdef.scene.entities[i];
4833                 r_refdef.stats.entities++;
4834                 if (ent->model && ent->model->Draw != NULL)
4835                         ent->model->Draw(ent);
4836                 else
4837                         R_DrawNoModel(ent);
4838         }
4839 }
4840
4841 static void R_DrawModelsDepth(void)
4842 {
4843         int i;
4844         entity_render_t *ent;
4845
4846         for (i = 0;i < r_refdef.scene.numentities;i++)
4847         {
4848                 if (!r_refdef.viewcache.entityvisible[i])
4849                         continue;
4850                 ent = r_refdef.scene.entities[i];
4851                 if (ent->model && ent->model->DrawDepth != NULL)
4852                         ent->model->DrawDepth(ent);
4853         }
4854 }
4855
4856 static void R_DrawModelsDebug(void)
4857 {
4858         int i;
4859         entity_render_t *ent;
4860
4861         for (i = 0;i < r_refdef.scene.numentities;i++)
4862         {
4863                 if (!r_refdef.viewcache.entityvisible[i])
4864                         continue;
4865                 ent = r_refdef.scene.entities[i];
4866                 if (ent->model && ent->model->DrawDebug != NULL)
4867                         ent->model->DrawDebug(ent);
4868         }
4869 }
4870
4871 static void R_DrawModelsAddWaterPlanes(void)
4872 {
4873         int i;
4874         entity_render_t *ent;
4875
4876         for (i = 0;i < r_refdef.scene.numentities;i++)
4877         {
4878                 if (!r_refdef.viewcache.entityvisible[i])
4879                         continue;
4880                 ent = r_refdef.scene.entities[i];
4881                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4882                         ent->model->DrawAddWaterPlanes(ent);
4883         }
4884 }
4885
4886 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4887 {
4888         if (r_hdr_irisadaptation.integer)
4889         {
4890                 vec3_t ambient;
4891                 vec3_t diffuse;
4892                 vec3_t diffusenormal;
4893                 vec_t brightness;
4894                 vec_t goal;
4895                 vec_t adjust;
4896                 vec_t current;
4897                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4898                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4899                 brightness = max(0.0000001f, brightness);
4900                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4901                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4902                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4903                 current = r_hdr_irisadaptation_value.value;
4904                 if (current < goal)
4905                         current = min(current + adjust, goal);
4906                 else if (current > goal)
4907                         current = max(current - adjust, goal);
4908                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4909                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4910         }
4911         else if (r_hdr_irisadaptation_value.value != 1.0f)
4912                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4913 }
4914
4915 static void R_View_SetFrustum(const int *scissor)
4916 {
4917         int i;
4918         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4919         vec3_t forward, left, up, origin, v;
4920
4921         if(scissor)
4922         {
4923                 // flipped x coordinates (because x points left here)
4924                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4925                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4926
4927                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4928                 switch(vid.renderpath)
4929                 {
4930                         case RENDERPATH_D3D9:
4931                         case RENDERPATH_D3D10:
4932                         case RENDERPATH_D3D11:
4933                         case RENDERPATH_SOFT:
4934                                 // non-flipped y coordinates
4935                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4936                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4937                                 break;
4938                         case RENDERPATH_GL11:
4939                         case RENDERPATH_GL13:
4940                         case RENDERPATH_GL20:
4941                         case RENDERPATH_GLES2:
4942                                 // non-flipped y coordinates
4943                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4944                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4945                                 break;
4946                 }
4947         }
4948
4949         // we can't trust r_refdef.view.forward and friends in reflected scenes
4950         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4951
4952 #if 0
4953         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4954         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4955         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4956         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4957         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4958         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4959         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4960         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4961         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4962         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4963         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4964         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4965 #endif
4966
4967 #if 0
4968         zNear = r_refdef.nearclip;
4969         nudge = 1.0 - 1.0 / (1<<23);
4970         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4971         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4972         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4973         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4974         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4975         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4976         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4977         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4978 #endif
4979
4980
4981
4982 #if 0
4983         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4984         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4985         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4986         r_refdef.view.frustum[0].dist = m[15] - m[12];
4987
4988         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4989         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4990         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4991         r_refdef.view.frustum[1].dist = m[15] + m[12];
4992
4993         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4994         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4995         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4996         r_refdef.view.frustum[2].dist = m[15] - m[13];
4997
4998         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4999         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5000         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5001         r_refdef.view.frustum[3].dist = m[15] + m[13];
5002
5003         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5004         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5005         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5006         r_refdef.view.frustum[4].dist = m[15] - m[14];
5007
5008         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5009         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5010         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5011         r_refdef.view.frustum[5].dist = m[15] + m[14];
5012 #endif
5013
5014         if (r_refdef.view.useperspective)
5015         {
5016                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5017                 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]);
5018                 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]);
5019                 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]);
5020                 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]);
5021
5022                 // then the normals from the corners relative to origin
5023                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5024                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5025                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5026                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5027
5028                 // in a NORMAL view, forward cross left == up
5029                 // in a REFLECTED view, forward cross left == down
5030                 // so our cross products above need to be adjusted for a left handed coordinate system
5031                 CrossProduct(forward, left, v);
5032                 if(DotProduct(v, up) < 0)
5033                 {
5034                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5035                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5036                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5037                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5038                 }
5039
5040                 // Leaving those out was a mistake, those were in the old code, and they
5041                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5042                 // I couldn't reproduce it after adding those normalizations. --blub
5043                 VectorNormalize(r_refdef.view.frustum[0].normal);
5044                 VectorNormalize(r_refdef.view.frustum[1].normal);
5045                 VectorNormalize(r_refdef.view.frustum[2].normal);
5046                 VectorNormalize(r_refdef.view.frustum[3].normal);
5047
5048                 // make the corners absolute
5049                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5050                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5051                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5052                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5053
5054                 // one more normal
5055                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5056
5057                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5058                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5059                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5060                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5061                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5062         }
5063         else
5064         {
5065                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5066                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5067                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5068                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5069                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5070                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5071                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5072                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5073                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5074                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5075         }
5076         r_refdef.view.numfrustumplanes = 5;
5077
5078         if (r_refdef.view.useclipplane)
5079         {
5080                 r_refdef.view.numfrustumplanes = 6;
5081                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5082         }
5083
5084         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5085                 PlaneClassify(r_refdef.view.frustum + i);
5086
5087         // LordHavoc: note to all quake engine coders, Quake had a special case
5088         // for 90 degrees which assumed a square view (wrong), so I removed it,
5089         // Quake2 has it disabled as well.
5090
5091         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5092         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5093         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5094         //PlaneClassify(&frustum[0]);
5095
5096         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5097         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5098         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5099         //PlaneClassify(&frustum[1]);
5100
5101         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5102         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5103         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5104         //PlaneClassify(&frustum[2]);
5105
5106         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5107         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5108         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5109         //PlaneClassify(&frustum[3]);
5110
5111         // nearclip plane
5112         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5113         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5114         //PlaneClassify(&frustum[4]);
5115 }
5116
5117 void R_View_UpdateWithScissor(const int *myscissor)
5118 {
5119         R_Main_ResizeViewCache();
5120         R_View_SetFrustum(myscissor);
5121         R_View_WorldVisibility(r_refdef.view.useclipplane);
5122         R_View_UpdateEntityVisible();
5123         R_View_UpdateEntityLighting();
5124 }
5125
5126 void R_View_Update(void)
5127 {
5128         R_Main_ResizeViewCache();
5129         R_View_SetFrustum(NULL);
5130         R_View_WorldVisibility(r_refdef.view.useclipplane);
5131         R_View_UpdateEntityVisible();
5132         R_View_UpdateEntityLighting();
5133 }
5134
5135 static float viewscalefpsadjusted = 1.0f;
5136
5137 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5138 {
5139         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5140         scale = bound(0.03125f, scale, 1.0f);
5141         *outwidth = (int)ceil(width * scale);
5142         *outheight = (int)ceil(height * scale);
5143 }
5144
5145 void R_Mesh_SetMainRenderTargets(void)
5146 {
5147         if (r_bloomstate.fbo_framebuffer)
5148                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5149         else
5150                 R_Mesh_ResetRenderTargets();
5151 }
5152
5153 void R_SetupView(qboolean allowwaterclippingplane)
5154 {
5155         const float *customclipplane = NULL;
5156         float plane[4];
5157         int scaledwidth, scaledheight;
5158         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5159         {
5160                 // LordHavoc: couldn't figure out how to make this approach the
5161                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5162                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5163                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5164                         dist = r_refdef.view.clipplane.dist;
5165                 plane[0] = r_refdef.view.clipplane.normal[0];
5166                 plane[1] = r_refdef.view.clipplane.normal[1];
5167                 plane[2] = r_refdef.view.clipplane.normal[2];
5168                 plane[3] = dist;
5169                 customclipplane = plane;
5170         }
5171
5172         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5173         if (!r_refdef.view.useperspective)
5174                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -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);
5175         else if (vid.stencil && r_useinfinitefarclip.integer)
5176                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5177         else
5178                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5179         R_Mesh_SetMainRenderTargets();
5180         R_SetViewport(&r_refdef.view.viewport);
5181 }
5182
5183 void R_EntityMatrix(const matrix4x4_t *matrix)
5184 {
5185         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5186         {
5187                 gl_modelmatrixchanged = false;
5188                 gl_modelmatrix = *matrix;
5189                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5190                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5191                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5192                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5193                 CHECKGLERROR
5194                 switch(vid.renderpath)
5195                 {
5196                 case RENDERPATH_D3D9:
5197 #ifdef SUPPORTD3D
5198                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5199                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5200 #endif
5201                         break;
5202                 case RENDERPATH_D3D10:
5203                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5204                         break;
5205                 case RENDERPATH_D3D11:
5206                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5207                         break;
5208                 case RENDERPATH_GL13:
5209                 case RENDERPATH_GL11:
5210                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5211                         break;
5212                 case RENDERPATH_SOFT:
5213                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5214                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5215                         break;
5216                 case RENDERPATH_GL20:
5217                 case RENDERPATH_GLES2:
5218                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5219                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5220                         break;
5221                 }
5222         }
5223 }
5224
5225 void R_ResetViewRendering2D(void)
5226 {
5227         r_viewport_t viewport;
5228         DrawQ_Finish();
5229
5230         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5231         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);
5232         R_Mesh_ResetRenderTargets();
5233         R_SetViewport(&viewport);
5234         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5235         GL_Color(1, 1, 1, 1);
5236         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5237         GL_BlendFunc(GL_ONE, GL_ZERO);
5238         GL_ScissorTest(false);
5239         GL_DepthMask(false);
5240         GL_DepthRange(0, 1);
5241         GL_DepthTest(false);
5242         GL_DepthFunc(GL_LEQUAL);
5243         R_EntityMatrix(&identitymatrix);
5244         R_Mesh_ResetTextureState();
5245         GL_PolygonOffset(0, 0);
5246         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5247         switch(vid.renderpath)
5248         {
5249         case RENDERPATH_GL11:
5250         case RENDERPATH_GL13:
5251         case RENDERPATH_GL20:
5252         case RENDERPATH_GLES2:
5253                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5254                 break;
5255         case RENDERPATH_D3D9:
5256         case RENDERPATH_D3D10:
5257         case RENDERPATH_D3D11:
5258         case RENDERPATH_SOFT:
5259                 break;
5260         }
5261         GL_CullFace(GL_NONE);
5262 }
5263
5264 void R_ResetViewRendering3D(void)
5265 {
5266         DrawQ_Finish();
5267
5268         R_SetupView(true);
5269         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5270         GL_Color(1, 1, 1, 1);
5271         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5272         GL_BlendFunc(GL_ONE, GL_ZERO);
5273         GL_ScissorTest(true);
5274         GL_DepthMask(true);
5275         GL_DepthRange(0, 1);
5276         GL_DepthTest(true);
5277         GL_DepthFunc(GL_LEQUAL);
5278         R_EntityMatrix(&identitymatrix);
5279         R_Mesh_ResetTextureState();
5280         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5281         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5282         switch(vid.renderpath)
5283         {
5284         case RENDERPATH_GL11:
5285         case RENDERPATH_GL13:
5286         case RENDERPATH_GL20:
5287         case RENDERPATH_GLES2:
5288                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5289                 break;
5290         case RENDERPATH_D3D9:
5291         case RENDERPATH_D3D10:
5292         case RENDERPATH_D3D11:
5293         case RENDERPATH_SOFT:
5294                 break;
5295         }
5296         GL_CullFace(r_refdef.view.cullface_back);
5297 }
5298
5299 /*
5300 ================
5301 R_RenderView_UpdateViewVectors
5302 ================
5303 */
5304 static void R_RenderView_UpdateViewVectors(void)
5305 {
5306         // break apart the view matrix into vectors for various purposes
5307         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5308         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5309         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5310         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5311         // make an inverted copy of the view matrix for tracking sprites
5312         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5313 }
5314
5315 void R_RenderScene(void);
5316 void R_RenderWaterPlanes(void);
5317
5318 static void R_Water_StartFrame(void)
5319 {
5320         int i;
5321         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5322         r_waterstate_waterplane_t *p;
5323
5324         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5325                 return;
5326
5327         switch(vid.renderpath)
5328         {
5329         case RENDERPATH_GL20:
5330         case RENDERPATH_D3D9:
5331         case RENDERPATH_D3D10:
5332         case RENDERPATH_D3D11:
5333         case RENDERPATH_SOFT:
5334         case RENDERPATH_GLES2:
5335                 break;
5336         case RENDERPATH_GL13:
5337         case RENDERPATH_GL11:
5338                 return;
5339         }
5340
5341         // set waterwidth and waterheight to the water resolution that will be
5342         // used (often less than the screen resolution for faster rendering)
5343         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5344         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5345
5346         // calculate desired texture sizes
5347         // can't use water if the card does not support the texture size
5348         if (!r_water.integer || r_showsurfaces.integer)
5349                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5350         else if (vid.support.arb_texture_non_power_of_two)
5351         {
5352                 texturewidth = waterwidth;
5353                 textureheight = waterheight;
5354                 camerawidth = waterwidth;
5355                 cameraheight = waterheight;
5356         }
5357         else
5358         {
5359                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5360                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5361                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5362                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5363         }
5364
5365         // allocate textures as needed
5366         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5367         {
5368                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5369                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5370                 {
5371                         if (p->texture_refraction)
5372                                 R_FreeTexture(p->texture_refraction);
5373                         p->texture_refraction = NULL;
5374                         if (p->texture_reflection)
5375                                 R_FreeTexture(p->texture_reflection);
5376                         p->texture_reflection = NULL;
5377                         if (p->texture_camera)
5378                                 R_FreeTexture(p->texture_camera);
5379                         p->texture_camera = NULL;
5380                 }
5381                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5382                 r_waterstate.texturewidth = texturewidth;
5383                 r_waterstate.textureheight = textureheight;
5384                 r_waterstate.camerawidth = camerawidth;
5385                 r_waterstate.cameraheight = cameraheight;
5386         }
5387
5388         if (r_waterstate.texturewidth)
5389         {
5390                 r_waterstate.enabled = true;
5391
5392                 // when doing a reduced render (HDR) we want to use a smaller area
5393                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5394                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5395
5396                 // set up variables that will be used in shader setup
5397                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5398                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5399                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5400                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5401         }
5402
5403         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5404         r_waterstate.numwaterplanes = 0;
5405 }
5406
5407 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5408 {
5409         int triangleindex, planeindex;
5410         const int *e;
5411         vec3_t vert[3];
5412         vec3_t normal;
5413         vec3_t center;
5414         mplane_t plane;
5415         r_waterstate_waterplane_t *p;
5416         texture_t *t = R_GetCurrentTexture(surface->texture);
5417
5418         // just use the first triangle with a valid normal for any decisions
5419         VectorClear(normal);
5420         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5421         {
5422                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5423                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5424                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5425                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5426                 if (VectorLength2(normal) >= 0.001)
5427                         break;
5428         }
5429
5430         VectorCopy(normal, plane.normal);
5431         VectorNormalize(plane.normal);
5432         plane.dist = DotProduct(vert[0], plane.normal);
5433         PlaneClassify(&plane);
5434         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5435         {
5436                 // skip backfaces (except if nocullface is set)
5437                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5438                         return;
5439                 VectorNegate(plane.normal, plane.normal);
5440                 plane.dist *= -1;
5441                 PlaneClassify(&plane);
5442         }
5443
5444
5445         // find a matching plane if there is one
5446         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5447                 if(p->camera_entity == t->camera_entity)
5448                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5449                                 break;
5450         if (planeindex >= r_waterstate.maxwaterplanes)
5451                 return; // nothing we can do, out of planes
5452
5453         // if this triangle does not fit any known plane rendered this frame, add one
5454         if (planeindex >= r_waterstate.numwaterplanes)
5455         {
5456                 // store the new plane
5457                 r_waterstate.numwaterplanes++;
5458                 p->plane = plane;
5459                 // clear materialflags and pvs
5460                 p->materialflags = 0;
5461                 p->pvsvalid = false;
5462                 p->camera_entity = t->camera_entity;
5463                 VectorCopy(surface->mins, p->mins);
5464                 VectorCopy(surface->maxs, p->maxs);
5465         }
5466         else
5467         {
5468                 // merge mins/maxs
5469                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5470                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5471                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5472                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5473                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5474                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5475         }
5476         // merge this surface's materialflags into the waterplane
5477         p->materialflags |= t->currentmaterialflags;
5478         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5479         {
5480                 // merge this surface's PVS into the waterplane
5481                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5482                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5483                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5484                 {
5485                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5486                         p->pvsvalid = true;
5487                 }
5488         }
5489 }
5490
5491 static void R_Water_ProcessPlanes(void)
5492 {
5493         int myscissor[4];
5494         r_refdef_view_t originalview;
5495         r_refdef_view_t myview;
5496         int planeindex;
5497         r_waterstate_waterplane_t *p;
5498         vec3_t visorigin;
5499
5500         originalview = r_refdef.view;
5501
5502         // make sure enough textures are allocated
5503         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5504         {
5505                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5506                 {
5507                         if (!p->texture_refraction)
5508                                 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);
5509                         if (!p->texture_refraction)
5510                                 goto error;
5511                 }
5512                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5513                 {
5514                         if (!p->texture_camera)
5515                                 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);
5516                         if (!p->texture_camera)
5517                                 goto error;
5518                 }
5519
5520                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5521                 {
5522                         if (!p->texture_reflection)
5523                                 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);
5524                         if (!p->texture_reflection)
5525                                 goto error;
5526                 }
5527         }
5528
5529         // render views
5530         r_refdef.view = originalview;
5531         r_refdef.view.showdebug = false;
5532         r_refdef.view.width = r_waterstate.waterwidth;
5533         r_refdef.view.height = r_waterstate.waterheight;
5534         r_refdef.view.useclipplane = true;
5535         myview = r_refdef.view;
5536         r_waterstate.renderingscene = true;
5537         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5538         {
5539                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5540                 {
5541                         r_refdef.view = myview;
5542                         if(r_water_scissormode.integer)
5543                         {
5544                                 R_SetupView(true);
5545                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5546                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5547                         }
5548
5549                         // render reflected scene and copy into texture
5550                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5551                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5552                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5553                         r_refdef.view.clipplane = p->plane;
5554
5555                         // reverse the cullface settings for this render
5556                         r_refdef.view.cullface_front = GL_FRONT;
5557                         r_refdef.view.cullface_back = GL_BACK;
5558                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5559                         {
5560                                 r_refdef.view.usecustompvs = true;
5561                                 if (p->pvsvalid)
5562                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5563                                 else
5564                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5565                         }
5566
5567                         R_ResetViewRendering3D();
5568                         R_ClearScreen(r_refdef.fogenabled);
5569                         if(r_water_scissormode.integer & 2)
5570                                 R_View_UpdateWithScissor(myscissor);
5571                         else
5572                                 R_View_Update();
5573                         if(r_water_scissormode.integer & 1)
5574                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5575                         R_RenderScene();
5576
5577                         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);
5578                 }
5579
5580                 // render the normal view scene and copy into texture
5581                 // (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)
5582                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5583                 {
5584                         r_refdef.view = myview;
5585                         if(r_water_scissormode.integer)
5586                         {
5587                                 R_SetupView(true);
5588                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5589                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5590                         }
5591
5592                         r_waterstate.renderingrefraction = true;
5593
5594                         r_refdef.view.clipplane = p->plane;
5595                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5596                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5597
5598                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5599                         {
5600                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5601                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5602                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5603                                 R_RenderView_UpdateViewVectors();
5604                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5605                                 {
5606                                         r_refdef.view.usecustompvs = true;
5607                                         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);
5608                                 }
5609                         }
5610
5611                         PlaneClassify(&r_refdef.view.clipplane);
5612
5613                         R_ResetViewRendering3D();
5614                         R_ClearScreen(r_refdef.fogenabled);
5615                         if(r_water_scissormode.integer & 2)
5616                                 R_View_UpdateWithScissor(myscissor);
5617                         else
5618                                 R_View_Update();
5619                         if(r_water_scissormode.integer & 1)
5620                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5621                         R_RenderScene();
5622
5623                         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);
5624                         r_waterstate.renderingrefraction = false;
5625                 }
5626                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5627                 {
5628                         r_refdef.view = myview;
5629
5630                         r_refdef.view.clipplane = p->plane;
5631                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5632                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5633
5634                         r_refdef.view.width = r_waterstate.camerawidth;
5635                         r_refdef.view.height = r_waterstate.cameraheight;
5636                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5637                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5638
5639                         if(p->camera_entity)
5640                         {
5641                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5642                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5643                         }
5644
5645                         // note: all of the view is used for displaying... so
5646                         // there is no use in scissoring
5647
5648                         // reverse the cullface settings for this render
5649                         r_refdef.view.cullface_front = GL_FRONT;
5650                         r_refdef.view.cullface_back = GL_BACK;
5651                         // also reverse the view matrix
5652                         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
5653                         R_RenderView_UpdateViewVectors();
5654                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5655                         {
5656                                 r_refdef.view.usecustompvs = true;
5657                                 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);
5658                         }
5659                         
5660                         // camera needs no clipplane
5661                         r_refdef.view.useclipplane = false;
5662
5663                         PlaneClassify(&r_refdef.view.clipplane);
5664
5665                         R_ResetViewRendering3D();
5666                         R_ClearScreen(r_refdef.fogenabled);
5667                         R_View_Update();
5668                         R_RenderScene();
5669
5670                         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);
5671                         r_waterstate.renderingrefraction = false;
5672                 }
5673
5674         }
5675         r_waterstate.renderingscene = false;
5676         r_refdef.view = originalview;
5677         R_ResetViewRendering3D();
5678         R_ClearScreen(r_refdef.fogenabled);
5679         R_View_Update();
5680         return;
5681 error:
5682         r_refdef.view = originalview;
5683         r_waterstate.renderingscene = false;
5684         Cvar_SetValueQuick(&r_water, 0);
5685         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5686         return;
5687 }
5688
5689 void R_Bloom_StartFrame(void)
5690 {
5691         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5692         int viewwidth, viewheight;
5693         textype_t textype;
5694
5695         if (r_viewscale_fpsscaling.integer)
5696         {
5697                 static double lastrealtime;
5698                 double actualframetime;
5699                 double targetframetime;
5700                 double adjust;
5701                 actualframetime = realtime - lastrealtime;
5702                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5703                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5704                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5705                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5706                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5707                 viewscalefpsadjusted += adjust;
5708                 lastrealtime = realtime;
5709                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5710         }
5711         else
5712                 viewscalefpsadjusted = 1.0f;
5713
5714         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5715
5716         switch(vid.renderpath)
5717         {
5718         case RENDERPATH_GL20:
5719         case RENDERPATH_D3D9:
5720         case RENDERPATH_D3D10:
5721         case RENDERPATH_D3D11:
5722         case RENDERPATH_SOFT:
5723         case RENDERPATH_GLES2:
5724                 break;
5725         case RENDERPATH_GL13:
5726         case RENDERPATH_GL11:
5727                 return;
5728         }
5729
5730         // set bloomwidth and bloomheight to the bloom resolution that will be
5731         // used (often less than the screen resolution for faster rendering)
5732         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5733         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5734         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5735         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5736         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5737
5738         // calculate desired texture sizes
5739         if (vid.support.arb_texture_non_power_of_two)
5740         {
5741                 screentexturewidth = vid.width;
5742                 screentextureheight = vid.height;
5743                 bloomtexturewidth = r_bloomstate.bloomwidth;
5744                 bloomtextureheight = r_bloomstate.bloomheight;
5745         }
5746         else
5747         {
5748                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5749                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5750                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5751                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5752         }
5753
5754         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))
5755         {
5756                 Cvar_SetValueQuick(&r_hdr, 0);
5757                 Cvar_SetValueQuick(&r_bloom, 0);
5758                 Cvar_SetValueQuick(&r_motionblur, 0);
5759                 Cvar_SetValueQuick(&r_damageblur, 0);
5760         }
5761
5762         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)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5763                 screentexturewidth = screentextureheight = 0;
5764         if (!r_hdr.integer && !r_bloom.integer)
5765                 bloomtexturewidth = bloomtextureheight = 0;
5766
5767         textype = TEXTYPE_COLORBUFFER;
5768         switch (vid.renderpath)
5769         {
5770         case RENDERPATH_GL20:
5771         case RENDERPATH_GLES2:
5772                 if (vid.support.ext_framebuffer_object)
5773                 {
5774                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5775                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5776                 }
5777                 break;
5778         case RENDERPATH_D3D9:
5779         case RENDERPATH_D3D10:
5780         case RENDERPATH_D3D11:
5781         case RENDERPATH_SOFT:
5782         case RENDERPATH_GL13:
5783         case RENDERPATH_GL11:
5784                 break;
5785         }
5786
5787         // allocate textures as needed
5788         if (r_bloomstate.screentexturewidth != screentexturewidth
5789          || r_bloomstate.screentextureheight != screentextureheight
5790          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5791          || r_bloomstate.bloomtextureheight != bloomtextureheight
5792          || r_bloomstate.texturetype != textype
5793          || r_bloomstate.viewfbo != r_viewfbo.integer)
5794         {
5795                 if (r_bloomstate.texture_bloom)
5796                         R_FreeTexture(r_bloomstate.texture_bloom);
5797                 r_bloomstate.texture_bloom = NULL;
5798                 if (r_bloomstate.texture_screen)
5799                         R_FreeTexture(r_bloomstate.texture_screen);
5800                 r_bloomstate.texture_screen = NULL;
5801                 if (r_bloomstate.fbo_framebuffer)
5802                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5803                 r_bloomstate.fbo_framebuffer = 0;
5804                 if (r_bloomstate.texture_framebuffercolor)
5805                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5806                 r_bloomstate.texture_framebuffercolor = NULL;
5807                 if (r_bloomstate.texture_framebufferdepth)
5808                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5809                 r_bloomstate.texture_framebufferdepth = NULL;
5810                 r_bloomstate.screentexturewidth = screentexturewidth;
5811                 r_bloomstate.screentextureheight = screentextureheight;
5812                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5813                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5814                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5815                 {
5816                         // FIXME: choose depth bits based on a cvar
5817                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5818                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5819                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5820                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5821                         // render depth into one texture and normalmap into the other
5822                         if (qglDrawBuffer)
5823                         {
5824                                 int status;
5825                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5826                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5827                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5828                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5829                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5830                         }
5831                 }
5832                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5833                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5834                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5835                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5836                 r_bloomstate.viewfbo = r_viewfbo.integer;
5837                 r_bloomstate.texturetype = textype;
5838         }
5839
5840         // when doing a reduced render (HDR) we want to use a smaller area
5841         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5842         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5843         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5844         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5845         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5846
5847         // set up a texcoord array for the full resolution screen image
5848         // (we have to keep this around to copy back during final render)
5849         r_bloomstate.screentexcoord2f[0] = 0;
5850         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5851         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5852         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5853         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5854         r_bloomstate.screentexcoord2f[5] = 0;
5855         r_bloomstate.screentexcoord2f[6] = 0;
5856         r_bloomstate.screentexcoord2f[7] = 0;
5857
5858         // set up a texcoord array for the reduced resolution bloom image
5859         // (which will be additive blended over the screen image)
5860         r_bloomstate.bloomtexcoord2f[0] = 0;
5861         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5862         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5863         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5864         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5865         r_bloomstate.bloomtexcoord2f[5] = 0;
5866         r_bloomstate.bloomtexcoord2f[6] = 0;
5867         r_bloomstate.bloomtexcoord2f[7] = 0;
5868
5869         switch(vid.renderpath)
5870         {
5871         case RENDERPATH_GL11:
5872         case RENDERPATH_GL13:
5873         case RENDERPATH_GL20:
5874         case RENDERPATH_SOFT:
5875         case RENDERPATH_GLES2:
5876                 break;
5877         case RENDERPATH_D3D9:
5878         case RENDERPATH_D3D10:
5879         case RENDERPATH_D3D11:
5880                 {
5881                         int i;
5882                         for (i = 0;i < 4;i++)
5883                         {
5884                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5885                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5886                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5887                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5888                         }
5889                 }
5890                 break;
5891         }
5892
5893         if (r_hdr.integer || r_bloom.integer)
5894         {
5895                 r_bloomstate.enabled = true;
5896                 r_bloomstate.hdr = r_hdr.integer != 0;
5897         }
5898
5899         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);
5900
5901         if (r_bloomstate.fbo_framebuffer)
5902                 r_refdef.view.clear = true;
5903 }
5904
5905 void R_Bloom_CopyBloomTexture(float colorscale)
5906 {
5907         r_refdef.stats.bloom++;
5908
5909         // scale down screen texture to the bloom texture size
5910         CHECKGLERROR
5911         R_Mesh_SetMainRenderTargets();
5912         R_SetViewport(&r_bloomstate.viewport);
5913         GL_BlendFunc(GL_ONE, GL_ZERO);
5914         GL_Color(colorscale, colorscale, colorscale, 1);
5915         // 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...
5916         switch(vid.renderpath)
5917         {
5918         case RENDERPATH_GL11:
5919         case RENDERPATH_GL13:
5920         case RENDERPATH_GL20:
5921         case RENDERPATH_SOFT:
5922         case RENDERPATH_GLES2:
5923                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5924                 break;
5925         case RENDERPATH_D3D9:
5926         case RENDERPATH_D3D10:
5927         case RENDERPATH_D3D11:
5928                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5929                 break;
5930         }
5931         // TODO: do boxfilter scale-down in shader?
5932         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5933         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5934         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5935
5936         // we now have a bloom image in the framebuffer
5937         // copy it into the bloom image texture for later processing
5938         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);
5939         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5940 }
5941
5942 void R_Bloom_CopyHDRTexture(void)
5943 {
5944         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);
5945         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5946 }
5947
5948 void R_Bloom_MakeTexture(void)
5949 {
5950         int x, range, dir;
5951         float xoffset, yoffset, r, brighten;
5952
5953         r_refdef.stats.bloom++;
5954
5955         R_ResetViewRendering2D();
5956
5957         // we have a bloom image in the framebuffer
5958         CHECKGLERROR
5959         R_SetViewport(&r_bloomstate.viewport);
5960
5961         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5962         {
5963                 x *= 2;
5964                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5965                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5966                 GL_Color(r,r,r,1);
5967                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5968                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5969                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5970                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5971
5972                 // copy the vertically blurred bloom view to a texture
5973                 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);
5974                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5975         }
5976
5977         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5978         brighten = r_bloom_brighten.value;
5979         if (r_hdr.integer)
5980                 brighten *= r_hdr_range.value;
5981         brighten = sqrt(brighten);
5982         if(range >= 1)
5983                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5984         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5985
5986         for (dir = 0;dir < 2;dir++)
5987         {
5988                 // blend on at multiple vertical offsets to achieve a vertical blur
5989                 // TODO: do offset blends using GLSL
5990                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5991                 GL_BlendFunc(GL_ONE, GL_ZERO);
5992                 for (x = -range;x <= range;x++)
5993                 {
5994                         if (!dir){xoffset = 0;yoffset = x;}
5995                         else {xoffset = x;yoffset = 0;}
5996                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5997                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5998                         // compute a texcoord array with the specified x and y offset
5999                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6000                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6001                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6002                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6003                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6004                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6005                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6006                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6007                         // this r value looks like a 'dot' particle, fading sharply to
6008                         // black at the edges
6009                         // (probably not realistic but looks good enough)
6010                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6011                         //r = brighten/(range*2+1);
6012                         r = brighten / (range * 2 + 1);
6013                         if(range >= 1)
6014                                 r *= (1 - x*x/(float)(range*range));
6015                         GL_Color(r, r, r, 1);
6016                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6017                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6018                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6019                         GL_BlendFunc(GL_ONE, GL_ONE);
6020                 }
6021
6022                 // copy the vertically blurred bloom view to a texture
6023                 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);
6024                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6025         }
6026 }
6027
6028 void R_HDR_RenderBloomTexture(void)
6029 {
6030         int oldwidth, oldheight;
6031         float oldcolorscale;
6032         qboolean oldwaterstate;
6033
6034         oldwaterstate = r_waterstate.enabled;
6035         oldcolorscale = r_refdef.view.colorscale;
6036         oldwidth = r_refdef.view.width;
6037         oldheight = r_refdef.view.height;
6038         r_refdef.view.width = r_bloomstate.bloomwidth;
6039         r_refdef.view.height = r_bloomstate.bloomheight;
6040
6041         if(r_hdr.integer < 2)
6042                 r_waterstate.enabled = false;
6043
6044         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6045         // TODO: add exposure compensation features
6046         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6047
6048         r_refdef.view.showdebug = false;
6049         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6050
6051         R_ResetViewRendering3D();
6052
6053         R_ClearScreen(r_refdef.fogenabled);
6054         if (r_timereport_active)
6055                 R_TimeReport("HDRclear");
6056
6057         R_View_Update();
6058         if (r_timereport_active)
6059                 R_TimeReport("visibility");
6060
6061         // only do secondary renders with HDR if r_hdr is 2 or higher
6062         r_waterstate.numwaterplanes = 0;
6063         if (r_waterstate.enabled)
6064                 R_RenderWaterPlanes();
6065
6066         r_refdef.view.showdebug = true;
6067         R_RenderScene();
6068         r_waterstate.numwaterplanes = 0;
6069
6070         R_ResetViewRendering2D();
6071
6072         R_Bloom_CopyHDRTexture();
6073         R_Bloom_MakeTexture();
6074
6075         // restore the view settings
6076         r_waterstate.enabled = oldwaterstate;
6077         r_refdef.view.width = oldwidth;
6078         r_refdef.view.height = oldheight;
6079         r_refdef.view.colorscale = oldcolorscale;
6080
6081         R_ResetViewRendering3D();
6082
6083         R_ClearScreen(r_refdef.fogenabled);
6084         if (r_timereport_active)
6085                 R_TimeReport("viewclear");
6086 }
6087
6088 static void R_BlendView(void)
6089 {
6090         unsigned int permutation;
6091         float uservecs[4][4];
6092
6093         switch (vid.renderpath)
6094         {
6095         case RENDERPATH_GL20:
6096         case RENDERPATH_D3D9:
6097         case RENDERPATH_D3D10:
6098         case RENDERPATH_D3D11:
6099         case RENDERPATH_SOFT:
6100         case RENDERPATH_GLES2:
6101                 permutation =
6102                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6103                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6104                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6105                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6106                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6107
6108                 if (r_bloomstate.texture_screen)
6109                 {
6110                         // make sure the buffer is available
6111                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6112
6113                         R_ResetViewRendering2D();
6114                         R_Mesh_SetMainRenderTargets();
6115
6116                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6117                         {
6118                                 // declare variables
6119                                 float speed;
6120                                 static float avgspeed;
6121
6122                                 speed = VectorLength(cl.movement_velocity);
6123
6124                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6125                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6126
6127                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6128                                 speed = bound(0, speed, 1);
6129                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6130
6131                                 // calculate values into a standard alpha
6132                                 cl.motionbluralpha = 1 - exp(-
6133                                                 (
6134                                                  (r_motionblur.value * speed / 80)
6135                                                  +
6136                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6137                                                 )
6138                                                 /
6139                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6140                                            );
6141
6142                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6143                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6144                                 // apply the blur
6145                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6146                                 {
6147                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6148                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6149                                         switch(vid.renderpath)
6150                                         {
6151                                         case RENDERPATH_GL11:
6152                                         case RENDERPATH_GL13:
6153                                         case RENDERPATH_GL20:
6154                                         case RENDERPATH_SOFT:
6155                                         case RENDERPATH_GLES2:
6156                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6157                                                 break;
6158                                         case RENDERPATH_D3D9:
6159                                         case RENDERPATH_D3D10:
6160                                         case RENDERPATH_D3D11:
6161                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6162                                                 break;
6163                                         }
6164                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6165                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6166                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6167                                 }
6168                         }
6169
6170                         // copy view into the screen texture
6171                         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);
6172                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6173                 }
6174                 else if (!r_bloomstate.texture_bloom)
6175                 {
6176                         // we may still have to do view tint...
6177                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6178                         {
6179                                 // apply a color tint to the whole view
6180                                 R_ResetViewRendering2D();
6181                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6182                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6183                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6184                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6185                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6186                         }
6187                         break; // no screen processing, no bloom, skip it
6188                 }
6189
6190                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6191                 {
6192                         // render simple bloom effect
6193                         // copy the screen and shrink it and darken it for the bloom process
6194                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6195                         // make the bloom texture
6196                         R_Bloom_MakeTexture();
6197                 }
6198
6199 #if _MSC_VER >= 1400
6200 #define sscanf sscanf_s
6201 #endif
6202                 memset(uservecs, 0, sizeof(uservecs));
6203                 if (r_glsl_postprocess_uservec1_enable.integer)
6204                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6205                 if (r_glsl_postprocess_uservec2_enable.integer)
6206                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6207                 if (r_glsl_postprocess_uservec3_enable.integer)
6208                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6209                 if (r_glsl_postprocess_uservec4_enable.integer)
6210                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6211
6212                 R_ResetViewRendering2D();
6213                 GL_Color(1, 1, 1, 1);
6214                 GL_BlendFunc(GL_ONE, GL_ZERO);
6215
6216                 switch(vid.renderpath)
6217                 {
6218                 case RENDERPATH_GL20:
6219                 case RENDERPATH_GLES2:
6220                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6221                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6222                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6223                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6224                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6225                         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]);
6226                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6227                         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]);
6228                         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]);
6229                         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]);
6230                         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]);
6231                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6232                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6233                         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);
6234                         break;
6235                 case RENDERPATH_D3D9:
6236 #ifdef SUPPORTD3D
6237                         // 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...
6238                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6239                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6240                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6241                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6242                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6243                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6244                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6245                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6246                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6247                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6248                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6249                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6250                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6251                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6252 #endif
6253                         break;
6254                 case RENDERPATH_D3D10:
6255                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6256                         break;
6257                 case RENDERPATH_D3D11:
6258                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6259                         break;
6260                 case RENDERPATH_SOFT:
6261                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6262                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6263                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6264                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6265                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6266                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6267                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6268                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6269                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6270                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6271                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6272                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6273                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6274                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6275                         break;
6276                 default:
6277                         break;
6278                 }
6279                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6280                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6281                 break;
6282         case RENDERPATH_GL13:
6283         case RENDERPATH_GL11:
6284                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6285                 {
6286                         // apply a color tint to the whole view
6287                         R_ResetViewRendering2D();
6288                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6289                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6290                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6291                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6292                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6293                 }
6294                 break;
6295         }
6296 }
6297
6298 matrix4x4_t r_waterscrollmatrix;
6299
6300 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6301 {
6302         if (r_refdef.fog_density)
6303         {
6304                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6305                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6306                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6307
6308                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6309                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6310                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6311                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6312
6313                 {
6314                         vec3_t fogvec;
6315                         VectorCopy(r_refdef.fogcolor, fogvec);
6316                         //   color.rgb *= ContrastBoost * SceneBrightness;
6317                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6318                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6319                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6320                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6321                 }
6322         }
6323 }
6324
6325 void R_UpdateVariables(void)
6326 {
6327         R_Textures_Frame();
6328
6329         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6330
6331         r_refdef.farclip = r_farclip_base.value;
6332         if (r_refdef.scene.worldmodel)
6333                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6334         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6335
6336         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6337                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6338         r_refdef.polygonfactor = 0;
6339         r_refdef.polygonoffset = 0;
6340         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6341         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6342
6343         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6344         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6345         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6346         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6347         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6348         if (FAKELIGHT_ENABLED)
6349         {
6350                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6351         }
6352         if (r_showsurfaces.integer)
6353         {
6354                 r_refdef.scene.rtworld = false;
6355                 r_refdef.scene.rtworldshadows = false;
6356                 r_refdef.scene.rtdlight = false;
6357                 r_refdef.scene.rtdlightshadows = false;
6358                 r_refdef.lightmapintensity = 0;
6359         }
6360
6361         if (gamemode == GAME_NEHAHRA)
6362         {
6363                 if (gl_fogenable.integer)
6364                 {
6365                         r_refdef.oldgl_fogenable = true;
6366                         r_refdef.fog_density = gl_fogdensity.value;
6367                         r_refdef.fog_red = gl_fogred.value;
6368                         r_refdef.fog_green = gl_foggreen.value;
6369                         r_refdef.fog_blue = gl_fogblue.value;
6370                         r_refdef.fog_alpha = 1;
6371                         r_refdef.fog_start = 0;
6372                         r_refdef.fog_end = gl_skyclip.value;
6373                         r_refdef.fog_height = 1<<30;
6374                         r_refdef.fog_fadedepth = 128;
6375                 }
6376                 else if (r_refdef.oldgl_fogenable)
6377                 {
6378                         r_refdef.oldgl_fogenable = false;
6379                         r_refdef.fog_density = 0;
6380                         r_refdef.fog_red = 0;
6381                         r_refdef.fog_green = 0;
6382                         r_refdef.fog_blue = 0;
6383                         r_refdef.fog_alpha = 0;
6384                         r_refdef.fog_start = 0;
6385                         r_refdef.fog_end = 0;
6386                         r_refdef.fog_height = 1<<30;
6387                         r_refdef.fog_fadedepth = 128;
6388                 }
6389         }
6390
6391         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6392         r_refdef.fog_start = max(0, r_refdef.fog_start);
6393         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6394
6395         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6396
6397         if (r_refdef.fog_density && r_drawfog.integer)
6398         {
6399                 r_refdef.fogenabled = true;
6400                 // this is the point where the fog reaches 0.9986 alpha, which we
6401                 // consider a good enough cutoff point for the texture
6402                 // (0.9986 * 256 == 255.6)
6403                 if (r_fog_exp2.integer)
6404                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6405                 else
6406                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6407                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6408                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6409                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6410                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6411                         R_BuildFogHeightTexture();
6412                 // fog color was already set
6413                 // update the fog texture
6414                 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)
6415                         R_BuildFogTexture();
6416                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6417                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6418         }
6419         else
6420                 r_refdef.fogenabled = false;
6421
6422         switch(vid.renderpath)
6423         {
6424         case RENDERPATH_GL20:
6425         case RENDERPATH_D3D9:
6426         case RENDERPATH_D3D10:
6427         case RENDERPATH_D3D11:
6428         case RENDERPATH_SOFT:
6429         case RENDERPATH_GLES2:
6430                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6431                 {
6432                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6433                         {
6434                                 // build GLSL gamma texture
6435 #define RAMPWIDTH 256
6436                                 unsigned short ramp[RAMPWIDTH * 3];
6437                                 unsigned char rampbgr[RAMPWIDTH][4];
6438                                 int i;
6439
6440                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6441
6442                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6443                                 for(i = 0; i < RAMPWIDTH; ++i)
6444                                 {
6445                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6446                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6447                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6448                                         rampbgr[i][3] = 0;
6449                                 }
6450                                 if (r_texture_gammaramps)
6451                                 {
6452                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6453                                 }
6454                                 else
6455                                 {
6456                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6457                                 }
6458                         }
6459                 }
6460                 else
6461                 {
6462                         // remove GLSL gamma texture
6463                 }
6464                 break;
6465         case RENDERPATH_GL13:
6466         case RENDERPATH_GL11:
6467                 break;
6468         }
6469 }
6470
6471 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6472 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6473 /*
6474 ================
6475 R_SelectScene
6476 ================
6477 */
6478 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6479         if( scenetype != r_currentscenetype ) {
6480                 // store the old scenetype
6481                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6482                 r_currentscenetype = scenetype;
6483                 // move in the new scene
6484                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6485         }
6486 }
6487
6488 /*
6489 ================
6490 R_GetScenePointer
6491 ================
6492 */
6493 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6494 {
6495         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6496         if( scenetype == r_currentscenetype ) {
6497                 return &r_refdef.scene;
6498         } else {
6499                 return &r_scenes_store[ scenetype ];
6500         }
6501 }
6502
6503 /*
6504 ================
6505 R_RenderView
6506 ================
6507 */
6508 int dpsoftrast_test;
6509 void R_RenderView(void)
6510 {
6511         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6512
6513         dpsoftrast_test = r_test.integer;
6514
6515         if (r_timereport_active)
6516                 R_TimeReport("start");
6517         r_textureframe++; // used only by R_GetCurrentTexture
6518         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6519
6520         if(R_CompileShader_CheckStaticParms())
6521                 R_GLSL_Restart_f();
6522
6523         if (!r_drawentities.integer)
6524                 r_refdef.scene.numentities = 0;
6525
6526         R_AnimCache_ClearCache();
6527         R_FrameData_NewFrame();
6528
6529         /* adjust for stereo display */
6530         if(R_Stereo_Active())
6531         {
6532                 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);
6533                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6534         }
6535
6536         if (r_refdef.view.isoverlay)
6537         {
6538                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6539                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6540                 R_TimeReport("depthclear");
6541
6542                 r_refdef.view.showdebug = false;
6543
6544                 r_waterstate.enabled = false;
6545                 r_waterstate.numwaterplanes = 0;
6546
6547                 R_RenderScene();
6548
6549                 r_refdef.view.matrix = originalmatrix;
6550
6551                 CHECKGLERROR
6552                 return;
6553         }
6554
6555         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6556         {
6557                 r_refdef.view.matrix = originalmatrix;
6558                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6559         }
6560
6561         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6562
6563         R_RenderView_UpdateViewVectors();
6564
6565         R_Shadow_UpdateWorldLightSelection();
6566
6567         R_Bloom_StartFrame();
6568         R_Water_StartFrame();
6569
6570         CHECKGLERROR
6571         if (r_timereport_active)
6572                 R_TimeReport("viewsetup");
6573
6574         R_ResetViewRendering3D();
6575
6576         if (r_refdef.view.clear || r_refdef.fogenabled)
6577         {
6578                 R_ClearScreen(r_refdef.fogenabled);
6579                 if (r_timereport_active)
6580                         R_TimeReport("viewclear");
6581         }
6582         r_refdef.view.clear = true;
6583
6584         // this produces a bloom texture to be used in R_BlendView() later
6585         if (r_hdr.integer && r_bloomstate.bloomwidth)
6586         {
6587                 R_HDR_RenderBloomTexture();
6588                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6589                 r_textureframe++; // used only by R_GetCurrentTexture
6590         }
6591
6592         r_refdef.view.showdebug = true;
6593
6594         R_View_Update();
6595         if (r_timereport_active)
6596                 R_TimeReport("visibility");
6597
6598         r_waterstate.numwaterplanes = 0;
6599         if (r_waterstate.enabled)
6600                 R_RenderWaterPlanes();
6601
6602         R_RenderScene();
6603         r_waterstate.numwaterplanes = 0;
6604
6605         R_BlendView();
6606         if (r_timereport_active)
6607                 R_TimeReport("blendview");
6608
6609         GL_Scissor(0, 0, vid.width, vid.height);
6610         GL_ScissorTest(false);
6611
6612         r_refdef.view.matrix = originalmatrix;
6613
6614         CHECKGLERROR
6615 }
6616
6617 void R_RenderWaterPlanes(void)
6618 {
6619         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6620         {
6621                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6622                 if (r_timereport_active)
6623                         R_TimeReport("waterworld");
6624         }
6625
6626         // don't let sound skip if going slow
6627         if (r_refdef.scene.extraupdate)
6628                 S_ExtraUpdate ();
6629
6630         R_DrawModelsAddWaterPlanes();
6631         if (r_timereport_active)
6632                 R_TimeReport("watermodels");
6633
6634         if (r_waterstate.numwaterplanes)
6635         {
6636                 R_Water_ProcessPlanes();
6637                 if (r_timereport_active)
6638                         R_TimeReport("waterscenes");
6639         }
6640 }
6641
6642 extern void R_DrawLightningBeams (void);
6643 extern void VM_CL_AddPolygonsToMeshQueue (void);
6644 extern void R_DrawPortals (void);
6645 extern cvar_t cl_locs_show;
6646 static void R_DrawLocs(void);
6647 static void R_DrawEntityBBoxes(void);
6648 static void R_DrawModelDecals(void);
6649 extern void R_DrawModelShadows(void);
6650 extern void R_DrawModelShadowMaps(void);
6651 extern cvar_t cl_decals_newsystem;
6652 extern qboolean r_shadow_usingdeferredprepass;
6653 void R_RenderScene(void)
6654 {
6655         qboolean shadowmapping = false;
6656
6657         if (r_timereport_active)
6658                 R_TimeReport("beginscene");
6659
6660         r_refdef.stats.renders++;
6661
6662         R_UpdateFogColor();
6663
6664         // don't let sound skip if going slow
6665         if (r_refdef.scene.extraupdate)
6666                 S_ExtraUpdate ();
6667
6668         R_MeshQueue_BeginScene();
6669
6670         R_SkyStartFrame();
6671
6672         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);
6673
6674         if (r_timereport_active)
6675                 R_TimeReport("skystartframe");
6676
6677         if (cl.csqc_vidvars.drawworld)
6678         {
6679                 // don't let sound skip if going slow
6680                 if (r_refdef.scene.extraupdate)
6681                         S_ExtraUpdate ();
6682
6683                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6684                 {
6685                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6686                         if (r_timereport_active)
6687                                 R_TimeReport("worldsky");
6688                 }
6689
6690                 if (R_DrawBrushModelsSky() && r_timereport_active)
6691                         R_TimeReport("bmodelsky");
6692
6693                 if (skyrendermasked && skyrenderlater)
6694                 {
6695                         // we have to force off the water clipping plane while rendering sky
6696                         R_SetupView(false);
6697                         R_Sky();
6698                         R_SetupView(true);
6699                         if (r_timereport_active)
6700                                 R_TimeReport("sky");
6701                 }
6702         }
6703
6704         R_AnimCache_CacheVisibleEntities();
6705         if (r_timereport_active)
6706                 R_TimeReport("animation");
6707
6708         R_Shadow_PrepareLights();
6709         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6710                 R_Shadow_PrepareModelShadows();
6711         if (r_timereport_active)
6712                 R_TimeReport("preparelights");
6713
6714         if (R_Shadow_ShadowMappingEnabled())
6715                 shadowmapping = true;
6716
6717         if (r_shadow_usingdeferredprepass)
6718                 R_Shadow_DrawPrepass();
6719
6720         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6721         {
6722                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6723                 if (r_timereport_active)
6724                         R_TimeReport("worlddepth");
6725         }
6726         if (r_depthfirst.integer >= 2)
6727         {
6728                 R_DrawModelsDepth();
6729                 if (r_timereport_active)
6730                         R_TimeReport("modeldepth");
6731         }
6732
6733         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6734         {
6735                 R_DrawModelShadowMaps();
6736                 R_ResetViewRendering3D();
6737                 // don't let sound skip if going slow
6738                 if (r_refdef.scene.extraupdate)
6739                         S_ExtraUpdate ();
6740         }
6741
6742         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6743         {
6744                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6745                 if (r_timereport_active)
6746                         R_TimeReport("world");
6747         }
6748
6749         // don't let sound skip if going slow
6750         if (r_refdef.scene.extraupdate)
6751                 S_ExtraUpdate ();
6752
6753         R_DrawModels();
6754         if (r_timereport_active)
6755                 R_TimeReport("models");
6756
6757         // don't let sound skip if going slow
6758         if (r_refdef.scene.extraupdate)
6759                 S_ExtraUpdate ();
6760
6761         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6762         {
6763                 R_DrawModelShadows();
6764                 R_ResetViewRendering3D();
6765                 // don't let sound skip if going slow
6766                 if (r_refdef.scene.extraupdate)
6767                         S_ExtraUpdate ();
6768         }
6769
6770         if (!r_shadow_usingdeferredprepass)
6771         {
6772                 R_Shadow_DrawLights();
6773                 if (r_timereport_active)
6774                         R_TimeReport("rtlights");
6775         }
6776
6777         // don't let sound skip if going slow
6778         if (r_refdef.scene.extraupdate)
6779                 S_ExtraUpdate ();
6780
6781         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6782         {
6783                 R_DrawModelShadows();
6784                 R_ResetViewRendering3D();
6785                 // don't let sound skip if going slow
6786                 if (r_refdef.scene.extraupdate)
6787                         S_ExtraUpdate ();
6788         }
6789
6790         if (cl.csqc_vidvars.drawworld)
6791         {
6792                 if (cl_decals_newsystem.integer)
6793                 {
6794                         R_DrawModelDecals();
6795                         if (r_timereport_active)
6796                                 R_TimeReport("modeldecals");
6797                 }
6798                 else
6799                 {
6800                         R_DrawDecals();
6801                         if (r_timereport_active)
6802                                 R_TimeReport("decals");
6803                 }
6804
6805                 R_DrawParticles();
6806                 if (r_timereport_active)
6807                         R_TimeReport("particles");
6808
6809                 R_DrawExplosions();
6810                 if (r_timereport_active)
6811                         R_TimeReport("explosions");
6812
6813                 R_DrawLightningBeams();
6814                 if (r_timereport_active)
6815                         R_TimeReport("lightning");
6816         }
6817
6818         VM_CL_AddPolygonsToMeshQueue();
6819
6820         if (r_refdef.view.showdebug)
6821         {
6822                 if (cl_locs_show.integer)
6823                 {
6824                         R_DrawLocs();
6825                         if (r_timereport_active)
6826                                 R_TimeReport("showlocs");
6827                 }
6828
6829                 if (r_drawportals.integer)
6830                 {
6831                         R_DrawPortals();
6832                         if (r_timereport_active)
6833                                 R_TimeReport("portals");
6834                 }
6835
6836                 if (r_showbboxes.value > 0)
6837                 {
6838                         R_DrawEntityBBoxes();
6839                         if (r_timereport_active)
6840                                 R_TimeReport("bboxes");
6841                 }
6842         }
6843
6844         R_MeshQueue_RenderTransparent();
6845         if (r_timereport_active)
6846                 R_TimeReport("drawtrans");
6847
6848         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))
6849         {
6850                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6851                 if (r_timereport_active)
6852                         R_TimeReport("worlddebug");
6853                 R_DrawModelsDebug();
6854                 if (r_timereport_active)
6855                         R_TimeReport("modeldebug");
6856         }
6857
6858         if (cl.csqc_vidvars.drawworld)
6859         {
6860                 R_Shadow_DrawCoronas();
6861                 if (r_timereport_active)
6862                         R_TimeReport("coronas");
6863         }
6864
6865 #if 0
6866         {
6867                 GL_DepthTest(false);
6868                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6869                 GL_Color(1, 1, 1, 1);
6870                 qglBegin(GL_POLYGON);
6871                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6872                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6873                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6874                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6875                 qglEnd();
6876                 qglBegin(GL_POLYGON);
6877                 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]);
6878                 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]);
6879                 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]);
6880                 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]);
6881                 qglEnd();
6882                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6883         }
6884 #endif
6885
6886         // don't let sound skip if going slow
6887         if (r_refdef.scene.extraupdate)
6888                 S_ExtraUpdate ();
6889
6890         R_ResetViewRendering2D();
6891 }
6892
6893 static const unsigned short bboxelements[36] =
6894 {
6895         5, 1, 3, 5, 3, 7,
6896         6, 2, 0, 6, 0, 4,
6897         7, 3, 2, 7, 2, 6,
6898         4, 0, 1, 4, 1, 5,
6899         4, 5, 7, 4, 7, 6,
6900         1, 0, 2, 1, 2, 3,
6901 };
6902
6903 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6904 {
6905         int i;
6906         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6907
6908         RSurf_ActiveWorldEntity();
6909
6910         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6911         GL_DepthMask(false);
6912         GL_DepthRange(0, 1);
6913         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6914 //      R_Mesh_ResetTextureState();
6915
6916         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6917         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6918         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6919         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6920         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6921         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6922         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6923         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6924         R_FillColors(color4f, 8, cr, cg, cb, ca);
6925         if (r_refdef.fogenabled)
6926         {
6927                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6928                 {
6929                         f1 = RSurf_FogVertex(v);
6930                         f2 = 1 - f1;
6931                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6932                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6933                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6934                 }
6935         }
6936         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6937         R_Mesh_ResetTextureState();
6938         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6939         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6940 }
6941
6942 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6943 {
6944         int i;
6945         float color[4];
6946         prvm_edict_t *edict;
6947         prvm_prog_t *prog_save = prog;
6948
6949         // this function draws bounding boxes of server entities
6950         if (!sv.active)
6951                 return;
6952
6953         GL_CullFace(GL_NONE);
6954         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6955
6956         prog = 0;
6957         SV_VM_Begin();
6958         for (i = 0;i < numsurfaces;i++)
6959         {
6960                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6961                 switch ((int)edict->fields.server->solid)
6962                 {
6963                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6964                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6965                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6966                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6967                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6968                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6969                 }
6970                 color[3] *= r_showbboxes.value;
6971                 color[3] = bound(0, color[3], 1);
6972                 GL_DepthTest(!r_showdisabledepthtest.integer);
6973                 GL_CullFace(r_refdef.view.cullface_front);
6974                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6975         }
6976         SV_VM_End();
6977         prog = prog_save;
6978 }
6979
6980 static void R_DrawEntityBBoxes(void)
6981 {
6982         int i;
6983         prvm_edict_t *edict;
6984         vec3_t center;
6985         prvm_prog_t *prog_save = prog;
6986
6987         // this function draws bounding boxes of server entities
6988         if (!sv.active)
6989                 return;
6990
6991         prog = 0;
6992         SV_VM_Begin();
6993         for (i = 0;i < prog->num_edicts;i++)
6994         {
6995                 edict = PRVM_EDICT_NUM(i);
6996                 if (edict->priv.server->free)
6997                         continue;
6998                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6999                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7000                         continue;
7001                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7002                         continue;
7003                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7004                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7005         }
7006         SV_VM_End();
7007         prog = prog_save;
7008 }
7009
7010 static const int nomodelelement3i[24] =
7011 {
7012         5, 2, 0,
7013         5, 1, 2,
7014         5, 0, 3,
7015         5, 3, 1,
7016         0, 2, 4,
7017         2, 1, 4,
7018         3, 0, 4,
7019         1, 3, 4
7020 };
7021
7022 static const unsigned short nomodelelement3s[24] =
7023 {
7024         5, 2, 0,
7025         5, 1, 2,
7026         5, 0, 3,
7027         5, 3, 1,
7028         0, 2, 4,
7029         2, 1, 4,
7030         3, 0, 4,
7031         1, 3, 4
7032 };
7033
7034 static const float nomodelvertex3f[6*3] =
7035 {
7036         -16,   0,   0,
7037          16,   0,   0,
7038           0, -16,   0,
7039           0,  16,   0,
7040           0,   0, -16,
7041           0,   0,  16
7042 };
7043
7044 static const float nomodelcolor4f[6*4] =
7045 {
7046         0.0f, 0.0f, 0.5f, 1.0f,
7047         0.0f, 0.0f, 0.5f, 1.0f,
7048         0.0f, 0.5f, 0.0f, 1.0f,
7049         0.0f, 0.5f, 0.0f, 1.0f,
7050         0.5f, 0.0f, 0.0f, 1.0f,
7051         0.5f, 0.0f, 0.0f, 1.0f
7052 };
7053
7054 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7055 {
7056         int i;
7057         float f1, f2, *c;
7058         float color4f[6*4];
7059
7060         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);
7061
7062         // this is only called once per entity so numsurfaces is always 1, and
7063         // surfacelist is always {0}, so this code does not handle batches
7064
7065         if (rsurface.ent_flags & RENDER_ADDITIVE)
7066         {
7067                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7068                 GL_DepthMask(false);
7069         }
7070         else if (rsurface.colormod[3] < 1)
7071         {
7072                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7073                 GL_DepthMask(false);
7074         }
7075         else
7076         {
7077                 GL_BlendFunc(GL_ONE, GL_ZERO);
7078                 GL_DepthMask(true);
7079         }
7080         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7081         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7082         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7083         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7084         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7085         for (i = 0, c = color4f;i < 6;i++, c += 4)
7086         {
7087                 c[0] *= rsurface.colormod[0];
7088                 c[1] *= rsurface.colormod[1];
7089                 c[2] *= rsurface.colormod[2];
7090                 c[3] *= rsurface.colormod[3];
7091         }
7092         if (r_refdef.fogenabled)
7093         {
7094                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7095                 {
7096                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7097                         f2 = 1 - f1;
7098                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7099                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7100                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7101                 }
7102         }
7103 //      R_Mesh_ResetTextureState();
7104         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7105         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7106         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7107 }
7108
7109 void R_DrawNoModel(entity_render_t *ent)
7110 {
7111         vec3_t org;
7112         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7113         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7114                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7115         else
7116                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7117 }
7118
7119 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7120 {
7121         vec3_t right1, right2, diff, normal;
7122
7123         VectorSubtract (org2, org1, normal);
7124
7125         // calculate 'right' vector for start
7126         VectorSubtract (r_refdef.view.origin, org1, diff);
7127         CrossProduct (normal, diff, right1);
7128         VectorNormalize (right1);
7129
7130         // calculate 'right' vector for end
7131         VectorSubtract (r_refdef.view.origin, org2, diff);
7132         CrossProduct (normal, diff, right2);
7133         VectorNormalize (right2);
7134
7135         vert[ 0] = org1[0] + width * right1[0];
7136         vert[ 1] = org1[1] + width * right1[1];
7137         vert[ 2] = org1[2] + width * right1[2];
7138         vert[ 3] = org1[0] - width * right1[0];
7139         vert[ 4] = org1[1] - width * right1[1];
7140         vert[ 5] = org1[2] - width * right1[2];
7141         vert[ 6] = org2[0] - width * right2[0];
7142         vert[ 7] = org2[1] - width * right2[1];
7143         vert[ 8] = org2[2] - width * right2[2];
7144         vert[ 9] = org2[0] + width * right2[0];
7145         vert[10] = org2[1] + width * right2[1];
7146         vert[11] = org2[2] + width * right2[2];
7147 }
7148
7149 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)
7150 {
7151         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7152         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7153         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7154         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7155         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7156         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7157         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7158         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7159         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7160         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7161         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7162         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7163 }
7164
7165 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7166 {
7167         int i;
7168         float *vertex3f;
7169         float v[3];
7170         VectorSet(v, x, y, z);
7171         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7172                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7173                         break;
7174         if (i == mesh->numvertices)
7175         {
7176                 if (mesh->numvertices < mesh->maxvertices)
7177                 {
7178                         VectorCopy(v, vertex3f);
7179                         mesh->numvertices++;
7180                 }
7181                 return mesh->numvertices;
7182         }
7183         else
7184                 return i;
7185 }
7186
7187 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7188 {
7189         int i;
7190         int *e, element[3];
7191         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7192         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7193         e = mesh->element3i + mesh->numtriangles * 3;
7194         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7195         {
7196                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7197                 if (mesh->numtriangles < mesh->maxtriangles)
7198                 {
7199                         *e++ = element[0];
7200                         *e++ = element[1];
7201                         *e++ = element[2];
7202                         mesh->numtriangles++;
7203                 }
7204                 element[1] = element[2];
7205         }
7206 }
7207
7208 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7209 {
7210         int i;
7211         int *e, element[3];
7212         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7213         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7214         e = mesh->element3i + mesh->numtriangles * 3;
7215         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7216         {
7217                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7218                 if (mesh->numtriangles < mesh->maxtriangles)
7219                 {
7220                         *e++ = element[0];
7221                         *e++ = element[1];
7222                         *e++ = element[2];
7223                         mesh->numtriangles++;
7224                 }
7225                 element[1] = element[2];
7226         }
7227 }
7228
7229 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7230 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7231 {
7232         int planenum, planenum2;
7233         int w;
7234         int tempnumpoints;
7235         mplane_t *plane, *plane2;
7236         double maxdist;
7237         double temppoints[2][256*3];
7238         // figure out how large a bounding box we need to properly compute this brush
7239         maxdist = 0;
7240         for (w = 0;w < numplanes;w++)
7241                 maxdist = max(maxdist, fabs(planes[w].dist));
7242         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7243         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7244         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7245         {
7246                 w = 0;
7247                 tempnumpoints = 4;
7248                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7249                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7250                 {
7251                         if (planenum2 == planenum)
7252                                 continue;
7253                         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);
7254                         w = !w;
7255                 }
7256                 if (tempnumpoints < 3)
7257                         continue;
7258                 // generate elements forming a triangle fan for this polygon
7259                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7260         }
7261 }
7262
7263 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)
7264 {
7265         texturelayer_t *layer;
7266         layer = t->currentlayers + t->currentnumlayers++;
7267         layer->type = type;
7268         layer->depthmask = depthmask;
7269         layer->blendfunc1 = blendfunc1;
7270         layer->blendfunc2 = blendfunc2;
7271         layer->texture = texture;
7272         layer->texmatrix = *matrix;
7273         layer->color[0] = r;
7274         layer->color[1] = g;
7275         layer->color[2] = b;
7276         layer->color[3] = a;
7277 }
7278
7279 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7280 {
7281         if(parms[0] == 0 && parms[1] == 0)
7282                 return false;
7283         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7284                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7285                         return false;
7286         return true;
7287 }
7288
7289 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7290 {
7291         double index, f;
7292         index = parms[2] + r_refdef.scene.time * parms[3];
7293         index -= floor(index);
7294         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7295         {
7296         default:
7297         case Q3WAVEFUNC_NONE:
7298         case Q3WAVEFUNC_NOISE:
7299         case Q3WAVEFUNC_COUNT:
7300                 f = 0;
7301                 break;
7302         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7303         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7304         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7305         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7306         case Q3WAVEFUNC_TRIANGLE:
7307                 index *= 4;
7308                 f = index - floor(index);
7309                 if (index < 1)
7310                         f = f;
7311                 else if (index < 2)
7312                         f = 1 - f;
7313                 else if (index < 3)
7314                         f = -f;
7315                 else
7316                         f = -(1 - f);
7317                 break;
7318         }
7319         f = parms[0] + parms[1] * f;
7320         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7321                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7322         return (float) f;
7323 }
7324
7325 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7326 {
7327         int w, h, idx;
7328         float f;
7329         float tcmat[12];
7330         matrix4x4_t matrix, temp;
7331         switch(tcmod->tcmod)
7332         {
7333                 case Q3TCMOD_COUNT:
7334                 case Q3TCMOD_NONE:
7335                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7336                                 matrix = r_waterscrollmatrix;
7337                         else
7338                                 matrix = identitymatrix;
7339                         break;
7340                 case Q3TCMOD_ENTITYTRANSLATE:
7341                         // this is used in Q3 to allow the gamecode to control texcoord
7342                         // scrolling on the entity, which is not supported in darkplaces yet.
7343                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7344                         break;
7345                 case Q3TCMOD_ROTATE:
7346                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7347                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7348                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7349                         break;
7350                 case Q3TCMOD_SCALE:
7351                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7352                         break;
7353                 case Q3TCMOD_SCROLL:
7354                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7355                         break;
7356                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7357                         w = (int) tcmod->parms[0];
7358                         h = (int) tcmod->parms[1];
7359                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7360                         f = f - floor(f);
7361                         idx = (int) floor(f * w * h);
7362                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7363                         break;
7364                 case Q3TCMOD_STRETCH:
7365                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7366                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7367                         break;
7368                 case Q3TCMOD_TRANSFORM:
7369                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7370                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7371                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7372                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7373                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7374                         break;
7375                 case Q3TCMOD_TURBULENT:
7376                         // this is handled in the RSurf_PrepareVertices function
7377                         matrix = identitymatrix;
7378                         break;
7379         }
7380         temp = *texmatrix;
7381         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7382 }
7383
7384 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7385 {
7386         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7387         char name[MAX_QPATH];
7388         skinframe_t *skinframe;
7389         unsigned char pixels[296*194];
7390         strlcpy(cache->name, skinname, sizeof(cache->name));
7391         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7392         if (developer_loading.integer)
7393                 Con_Printf("loading %s\n", name);
7394         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7395         if (!skinframe || !skinframe->base)
7396         {
7397                 unsigned char *f;
7398                 fs_offset_t filesize;
7399                 skinframe = NULL;
7400                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7401                 if (f)
7402                 {
7403                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7404                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7405                         Mem_Free(f);
7406                 }
7407         }
7408         cache->skinframe = skinframe;
7409 }
7410
7411 texture_t *R_GetCurrentTexture(texture_t *t)
7412 {
7413         int i;
7414         const entity_render_t *ent = rsurface.entity;
7415         dp_model_t *model = ent->model;
7416         q3shaderinfo_layer_tcmod_t *tcmod;
7417
7418         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7419                 return t->currentframe;
7420         t->update_lastrenderframe = r_textureframe;
7421         t->update_lastrenderentity = (void *)ent;
7422
7423         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7424                 t->camera_entity = ent->entitynumber;
7425         else
7426                 t->camera_entity = 0;
7427
7428         // switch to an alternate material if this is a q1bsp animated material
7429         {
7430                 texture_t *texture = t;
7431                 int s = rsurface.ent_skinnum;
7432                 if ((unsigned int)s >= (unsigned int)model->numskins)
7433                         s = 0;
7434                 if (model->skinscenes)
7435                 {
7436                         if (model->skinscenes[s].framecount > 1)
7437                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7438                         else
7439                                 s = model->skinscenes[s].firstframe;
7440                 }
7441                 if (s > 0)
7442                         t = t + s * model->num_surfaces;
7443                 if (t->animated)
7444                 {
7445                         // use an alternate animation if the entity's frame is not 0,
7446                         // and only if the texture has an alternate animation
7447                         if (rsurface.ent_alttextures && t->anim_total[1])
7448                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7449                         else
7450                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7451                 }
7452                 texture->currentframe = t;
7453         }
7454
7455         // update currentskinframe to be a qw skin or animation frame
7456         if (rsurface.ent_qwskin >= 0)
7457         {
7458                 i = rsurface.ent_qwskin;
7459                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7460                 {
7461                         r_qwskincache_size = cl.maxclients;
7462                         if (r_qwskincache)
7463                                 Mem_Free(r_qwskincache);
7464                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7465                 }
7466                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7467                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7468                 t->currentskinframe = r_qwskincache[i].skinframe;
7469                 if (t->currentskinframe == NULL)
7470                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7471         }
7472         else if (t->numskinframes >= 2)
7473                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7474         if (t->backgroundnumskinframes >= 2)
7475                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7476
7477         t->currentmaterialflags = t->basematerialflags;
7478         t->currentalpha = rsurface.colormod[3];
7479         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7480                 t->currentalpha *= r_wateralpha.value;
7481         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7482                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7483         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7484                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7485         if (!(rsurface.ent_flags & RENDER_LIGHT))
7486                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7487         else if (FAKELIGHT_ENABLED)
7488         {
7489                         // no modellight if using fakelight for the map
7490         }
7491         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7492         {
7493                 // pick a model lighting mode
7494                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7495                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7496                 else
7497                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7498         }
7499         if (rsurface.ent_flags & RENDER_ADDITIVE)
7500                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7501         else if (t->currentalpha < 1)
7502                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7503         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7504                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7505         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7506                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7507         if (t->backgroundnumskinframes)
7508                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7509         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7510         {
7511                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7512                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7513         }
7514         else
7515                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7516         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7517                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7518
7519         // there is no tcmod
7520         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7521         {
7522                 t->currenttexmatrix = r_waterscrollmatrix;
7523                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7524         }
7525         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7526         {
7527                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7528                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7529         }
7530
7531         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7532                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7533         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7534                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7535
7536         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7537         if (t->currentskinframe->qpixels)
7538                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7539         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7540         if (!t->basetexture)
7541                 t->basetexture = r_texture_notexture;
7542         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7543         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7544         t->nmaptexture = t->currentskinframe->nmap;
7545         if (!t->nmaptexture)
7546                 t->nmaptexture = r_texture_blanknormalmap;
7547         t->glosstexture = r_texture_black;
7548         t->glowtexture = t->currentskinframe->glow;
7549         t->fogtexture = t->currentskinframe->fog;
7550         t->reflectmasktexture = t->currentskinframe->reflect;
7551         if (t->backgroundnumskinframes)
7552         {
7553                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7554                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7555                 t->backgroundglosstexture = r_texture_black;
7556                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7557                 if (!t->backgroundnmaptexture)
7558                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7559         }
7560         else
7561         {
7562                 t->backgroundbasetexture = r_texture_white;
7563                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7564                 t->backgroundglosstexture = r_texture_black;
7565                 t->backgroundglowtexture = NULL;
7566         }
7567         t->specularpower = r_shadow_glossexponent.value;
7568         // TODO: store reference values for these in the texture?
7569         t->specularscale = 0;
7570         if (r_shadow_gloss.integer > 0)
7571         {
7572                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7573                 {
7574                         if (r_shadow_glossintensity.value > 0)
7575                         {
7576                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7577                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7578                                 t->specularscale = r_shadow_glossintensity.value;
7579                         }
7580                 }
7581                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7582                 {
7583                         t->glosstexture = r_texture_white;
7584                         t->backgroundglosstexture = r_texture_white;
7585                         t->specularscale = r_shadow_gloss2intensity.value;
7586                         t->specularpower = r_shadow_gloss2exponent.value;
7587                 }
7588         }
7589         t->specularscale *= t->specularscalemod;
7590         t->specularpower *= t->specularpowermod;
7591
7592         // lightmaps mode looks bad with dlights using actual texturing, so turn
7593         // off the colormap and glossmap, but leave the normalmap on as it still
7594         // accurately represents the shading involved
7595         if (gl_lightmaps.integer)
7596         {
7597                 t->basetexture = r_texture_grey128;
7598                 t->pantstexture = r_texture_black;
7599                 t->shirttexture = r_texture_black;
7600                 t->nmaptexture = r_texture_blanknormalmap;
7601                 t->glosstexture = r_texture_black;
7602                 t->glowtexture = NULL;
7603                 t->fogtexture = NULL;
7604                 t->reflectmasktexture = NULL;
7605                 t->backgroundbasetexture = NULL;
7606                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7607                 t->backgroundglosstexture = r_texture_black;
7608                 t->backgroundglowtexture = NULL;
7609                 t->specularscale = 0;
7610                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7611         }
7612
7613         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7614         VectorClear(t->dlightcolor);
7615         t->currentnumlayers = 0;
7616         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7617         {
7618                 int blendfunc1, blendfunc2;
7619                 qboolean depthmask;
7620                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7621                 {
7622                         blendfunc1 = GL_SRC_ALPHA;
7623                         blendfunc2 = GL_ONE;
7624                 }
7625                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7626                 {
7627                         blendfunc1 = GL_SRC_ALPHA;
7628                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7629                 }
7630                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7631                 {
7632                         blendfunc1 = t->customblendfunc[0];
7633                         blendfunc2 = t->customblendfunc[1];
7634                 }
7635                 else
7636                 {
7637                         blendfunc1 = GL_ONE;
7638                         blendfunc2 = GL_ZERO;
7639                 }
7640                 // don't colormod evilblend textures
7641                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7642                         VectorSet(t->lightmapcolor, 1, 1, 1);
7643                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7644                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7645                 {
7646                         // fullbright is not affected by r_refdef.lightmapintensity
7647                         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]);
7648                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7649                                 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]);
7650                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7651                                 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]);
7652                 }
7653                 else
7654                 {
7655                         vec3_t ambientcolor;
7656                         float colorscale;
7657                         // set the color tint used for lights affecting this surface
7658                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7659                         colorscale = 2;
7660                         // q3bsp has no lightmap updates, so the lightstylevalue that
7661                         // would normally be baked into the lightmap must be
7662                         // applied to the color
7663                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7664                         if (model->type == mod_brushq3)
7665                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7666                         colorscale *= r_refdef.lightmapintensity;
7667                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7668                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7669                         // basic lit geometry
7670                         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]);
7671                         // add pants/shirt if needed
7672                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7673                                 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]);
7674                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7675                                 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]);
7676                         // now add ambient passes if needed
7677                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7678                         {
7679                                 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]);
7680                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7681                                         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]);
7682                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7683                                         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]);
7684                         }
7685                 }
7686                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7687                         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]);
7688                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7689                 {
7690                         // if this is opaque use alpha blend which will darken the earlier
7691                         // passes cheaply.
7692                         //
7693                         // if this is an alpha blended material, all the earlier passes
7694                         // were darkened by fog already, so we only need to add the fog
7695                         // color ontop through the fog mask texture
7696                         //
7697                         // if this is an additive blended material, all the earlier passes
7698                         // were darkened by fog already, and we should not add fog color
7699                         // (because the background was not darkened, there is no fog color
7700                         // that was lost behind it).
7701                         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]);
7702                 }
7703         }
7704
7705         return t->currentframe;
7706 }
7707
7708 rsurfacestate_t rsurface;
7709
7710 void RSurf_ActiveWorldEntity(void)
7711 {
7712         dp_model_t *model = r_refdef.scene.worldmodel;
7713         //if (rsurface.entity == r_refdef.scene.worldentity)
7714         //      return;
7715         rsurface.entity = r_refdef.scene.worldentity;
7716         rsurface.skeleton = NULL;
7717         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7718         rsurface.ent_skinnum = 0;
7719         rsurface.ent_qwskin = -1;
7720         rsurface.ent_shadertime = 0;
7721         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7722         rsurface.matrix = identitymatrix;
7723         rsurface.inversematrix = identitymatrix;
7724         rsurface.matrixscale = 1;
7725         rsurface.inversematrixscale = 1;
7726         R_EntityMatrix(&identitymatrix);
7727         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7728         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7729         rsurface.fograngerecip = r_refdef.fograngerecip;
7730         rsurface.fogheightfade = r_refdef.fogheightfade;
7731         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7732         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7733         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7734         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7735         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7736         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7737         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7738         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7739         rsurface.colormod[3] = 1;
7740         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);
7741         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7742         rsurface.frameblend[0].lerp = 1;
7743         rsurface.ent_alttextures = false;
7744         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7745         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7746         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7747         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7748         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7749         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7750         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7751         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7752         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7753         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7754         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7755         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7756         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7757         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7758         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7759         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7760         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7761         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7762         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7763         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7764         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7765         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7766         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7767         rsurface.modelelement3i = model->surfmesh.data_element3i;
7768         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7769         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7770         rsurface.modelelement3s = model->surfmesh.data_element3s;
7771         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7772         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7773         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7774         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7775         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7776         rsurface.modelsurfaces = model->data_surfaces;
7777         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7778         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7779         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7780         rsurface.modelgeneratedvertex = false;
7781         rsurface.batchgeneratedvertex = false;
7782         rsurface.batchfirstvertex = 0;
7783         rsurface.batchnumvertices = 0;
7784         rsurface.batchfirsttriangle = 0;
7785         rsurface.batchnumtriangles = 0;
7786         rsurface.batchvertex3f  = NULL;
7787         rsurface.batchvertex3f_vertexbuffer = NULL;
7788         rsurface.batchvertex3f_bufferoffset = 0;
7789         rsurface.batchsvector3f = NULL;
7790         rsurface.batchsvector3f_vertexbuffer = NULL;
7791         rsurface.batchsvector3f_bufferoffset = 0;
7792         rsurface.batchtvector3f = NULL;
7793         rsurface.batchtvector3f_vertexbuffer = NULL;
7794         rsurface.batchtvector3f_bufferoffset = 0;
7795         rsurface.batchnormal3f  = NULL;
7796         rsurface.batchnormal3f_vertexbuffer = NULL;
7797         rsurface.batchnormal3f_bufferoffset = 0;
7798         rsurface.batchlightmapcolor4f = NULL;
7799         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7800         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7801         rsurface.batchtexcoordtexture2f = NULL;
7802         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7803         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7804         rsurface.batchtexcoordlightmap2f = NULL;
7805         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7806         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7807         rsurface.batchvertexmesh = NULL;
7808         rsurface.batchvertexmeshbuffer = NULL;
7809         rsurface.batchvertex3fbuffer = NULL;
7810         rsurface.batchelement3i = NULL;
7811         rsurface.batchelement3i_indexbuffer = NULL;
7812         rsurface.batchelement3i_bufferoffset = 0;
7813         rsurface.batchelement3s = NULL;
7814         rsurface.batchelement3s_indexbuffer = NULL;
7815         rsurface.batchelement3s_bufferoffset = 0;
7816         rsurface.passcolor4f = NULL;
7817         rsurface.passcolor4f_vertexbuffer = NULL;
7818         rsurface.passcolor4f_bufferoffset = 0;
7819 }
7820
7821 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7822 {
7823         dp_model_t *model = ent->model;
7824         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7825         //      return;
7826         rsurface.entity = (entity_render_t *)ent;
7827         rsurface.skeleton = ent->skeleton;
7828         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7829         rsurface.ent_skinnum = ent->skinnum;
7830         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;
7831         rsurface.ent_shadertime = ent->shadertime;
7832         rsurface.ent_flags = ent->flags;
7833         rsurface.matrix = ent->matrix;
7834         rsurface.inversematrix = ent->inversematrix;
7835         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7836         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7837         R_EntityMatrix(&rsurface.matrix);
7838         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7839         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7840         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7841         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7842         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7843         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7844         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7845         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7846         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7847         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7848         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7849         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7850         rsurface.colormod[3] = ent->alpha;
7851         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7852         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7853         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7854         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7855         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7856         if (ent->model->brush.submodel && !prepass)
7857         {
7858                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7859                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7860         }
7861         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7862         {
7863                 if (ent->animcache_vertex3f)
7864                 {
7865                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7866                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7867                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7868                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7869                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7870                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7871                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7872                 }
7873                 else if (wanttangents)
7874                 {
7875                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7876                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7877                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7878                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7879                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7880                         rsurface.modelvertexmesh = NULL;
7881                         rsurface.modelvertexmeshbuffer = NULL;
7882                         rsurface.modelvertex3fbuffer = NULL;
7883                 }
7884                 else if (wantnormals)
7885                 {
7886                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7887                         rsurface.modelsvector3f = NULL;
7888                         rsurface.modeltvector3f = NULL;
7889                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7890                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7891                         rsurface.modelvertexmesh = NULL;
7892                         rsurface.modelvertexmeshbuffer = NULL;
7893                         rsurface.modelvertex3fbuffer = NULL;
7894                 }
7895                 else
7896                 {
7897                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7898                         rsurface.modelsvector3f = NULL;
7899                         rsurface.modeltvector3f = NULL;
7900                         rsurface.modelnormal3f = NULL;
7901                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7902                         rsurface.modelvertexmesh = NULL;
7903                         rsurface.modelvertexmeshbuffer = NULL;
7904                         rsurface.modelvertex3fbuffer = NULL;
7905                 }
7906                 rsurface.modelvertex3f_vertexbuffer = 0;
7907                 rsurface.modelvertex3f_bufferoffset = 0;
7908                 rsurface.modelsvector3f_vertexbuffer = 0;
7909                 rsurface.modelsvector3f_bufferoffset = 0;
7910                 rsurface.modeltvector3f_vertexbuffer = 0;
7911                 rsurface.modeltvector3f_bufferoffset = 0;
7912                 rsurface.modelnormal3f_vertexbuffer = 0;
7913                 rsurface.modelnormal3f_bufferoffset = 0;
7914                 rsurface.modelgeneratedvertex = true;
7915         }
7916         else
7917         {
7918                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7919                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7920                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7921                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7922                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7923                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7924                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7925                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7926                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7927                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7928                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7929                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7930                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7931                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7932                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7933                 rsurface.modelgeneratedvertex = false;
7934         }
7935         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7936         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7937         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7938         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7939         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7940         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7941         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7942         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7943         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7944         rsurface.modelelement3i = model->surfmesh.data_element3i;
7945         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7946         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7947         rsurface.modelelement3s = model->surfmesh.data_element3s;
7948         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7949         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7950         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7951         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7952         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7953         rsurface.modelsurfaces = model->data_surfaces;
7954         rsurface.batchgeneratedvertex = false;
7955         rsurface.batchfirstvertex = 0;
7956         rsurface.batchnumvertices = 0;
7957         rsurface.batchfirsttriangle = 0;
7958         rsurface.batchnumtriangles = 0;
7959         rsurface.batchvertex3f  = NULL;
7960         rsurface.batchvertex3f_vertexbuffer = NULL;
7961         rsurface.batchvertex3f_bufferoffset = 0;
7962         rsurface.batchsvector3f = NULL;
7963         rsurface.batchsvector3f_vertexbuffer = NULL;
7964         rsurface.batchsvector3f_bufferoffset = 0;
7965         rsurface.batchtvector3f = NULL;
7966         rsurface.batchtvector3f_vertexbuffer = NULL;
7967         rsurface.batchtvector3f_bufferoffset = 0;
7968         rsurface.batchnormal3f  = NULL;
7969         rsurface.batchnormal3f_vertexbuffer = NULL;
7970         rsurface.batchnormal3f_bufferoffset = 0;
7971         rsurface.batchlightmapcolor4f = NULL;
7972         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7973         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7974         rsurface.batchtexcoordtexture2f = NULL;
7975         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7976         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7977         rsurface.batchtexcoordlightmap2f = NULL;
7978         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7979         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7980         rsurface.batchvertexmesh = NULL;
7981         rsurface.batchvertexmeshbuffer = NULL;
7982         rsurface.batchvertex3fbuffer = NULL;
7983         rsurface.batchelement3i = NULL;
7984         rsurface.batchelement3i_indexbuffer = NULL;
7985         rsurface.batchelement3i_bufferoffset = 0;
7986         rsurface.batchelement3s = NULL;
7987         rsurface.batchelement3s_indexbuffer = NULL;
7988         rsurface.batchelement3s_bufferoffset = 0;
7989         rsurface.passcolor4f = NULL;
7990         rsurface.passcolor4f_vertexbuffer = NULL;
7991         rsurface.passcolor4f_bufferoffset = 0;
7992 }
7993
7994 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)
7995 {
7996         rsurface.entity = r_refdef.scene.worldentity;
7997         rsurface.skeleton = NULL;
7998         rsurface.ent_skinnum = 0;
7999         rsurface.ent_qwskin = -1;
8000         rsurface.ent_shadertime = shadertime;
8001         rsurface.ent_flags = entflags;
8002         rsurface.modelnumvertices = numvertices;
8003         rsurface.modelnumtriangles = numtriangles;
8004         rsurface.matrix = *matrix;
8005         rsurface.inversematrix = *inversematrix;
8006         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8007         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8008         R_EntityMatrix(&rsurface.matrix);
8009         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8010         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8011         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8012         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8013         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8014         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8015         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8016         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8017         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8018         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8019         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8020         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8021         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);
8022         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8023         rsurface.frameblend[0].lerp = 1;
8024         rsurface.ent_alttextures = false;
8025         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8026         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8027         if (wanttangents)
8028         {
8029                 rsurface.modelvertex3f = (float *)vertex3f;
8030                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8031                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8032                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8033         }
8034         else if (wantnormals)
8035         {
8036                 rsurface.modelvertex3f = (float *)vertex3f;
8037                 rsurface.modelsvector3f = NULL;
8038                 rsurface.modeltvector3f = NULL;
8039                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8040         }
8041         else
8042         {
8043                 rsurface.modelvertex3f = (float *)vertex3f;
8044                 rsurface.modelsvector3f = NULL;
8045                 rsurface.modeltvector3f = NULL;
8046                 rsurface.modelnormal3f = NULL;
8047         }
8048         rsurface.modelvertexmesh = NULL;
8049         rsurface.modelvertexmeshbuffer = NULL;
8050         rsurface.modelvertex3fbuffer = NULL;
8051         rsurface.modelvertex3f_vertexbuffer = 0;
8052         rsurface.modelvertex3f_bufferoffset = 0;
8053         rsurface.modelsvector3f_vertexbuffer = 0;
8054         rsurface.modelsvector3f_bufferoffset = 0;
8055         rsurface.modeltvector3f_vertexbuffer = 0;
8056         rsurface.modeltvector3f_bufferoffset = 0;
8057         rsurface.modelnormal3f_vertexbuffer = 0;
8058         rsurface.modelnormal3f_bufferoffset = 0;
8059         rsurface.modelgeneratedvertex = true;
8060         rsurface.modellightmapcolor4f  = (float *)color4f;
8061         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8062         rsurface.modellightmapcolor4f_bufferoffset = 0;
8063         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8064         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8065         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8066         rsurface.modeltexcoordlightmap2f  = NULL;
8067         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8068         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8069         rsurface.modelelement3i = (int *)element3i;
8070         rsurface.modelelement3i_indexbuffer = NULL;
8071         rsurface.modelelement3i_bufferoffset = 0;
8072         rsurface.modelelement3s = (unsigned short *)element3s;
8073         rsurface.modelelement3s_indexbuffer = NULL;
8074         rsurface.modelelement3s_bufferoffset = 0;
8075         rsurface.modellightmapoffsets = NULL;
8076         rsurface.modelsurfaces = NULL;
8077         rsurface.batchgeneratedvertex = false;
8078         rsurface.batchfirstvertex = 0;
8079         rsurface.batchnumvertices = 0;
8080         rsurface.batchfirsttriangle = 0;
8081         rsurface.batchnumtriangles = 0;
8082         rsurface.batchvertex3f  = NULL;
8083         rsurface.batchvertex3f_vertexbuffer = NULL;
8084         rsurface.batchvertex3f_bufferoffset = 0;
8085         rsurface.batchsvector3f = NULL;
8086         rsurface.batchsvector3f_vertexbuffer = NULL;
8087         rsurface.batchsvector3f_bufferoffset = 0;
8088         rsurface.batchtvector3f = NULL;
8089         rsurface.batchtvector3f_vertexbuffer = NULL;
8090         rsurface.batchtvector3f_bufferoffset = 0;
8091         rsurface.batchnormal3f  = NULL;
8092         rsurface.batchnormal3f_vertexbuffer = NULL;
8093         rsurface.batchnormal3f_bufferoffset = 0;
8094         rsurface.batchlightmapcolor4f = NULL;
8095         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8096         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8097         rsurface.batchtexcoordtexture2f = NULL;
8098         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8099         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8100         rsurface.batchtexcoordlightmap2f = NULL;
8101         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8102         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8103         rsurface.batchvertexmesh = NULL;
8104         rsurface.batchvertexmeshbuffer = NULL;
8105         rsurface.batchvertex3fbuffer = NULL;
8106         rsurface.batchelement3i = NULL;
8107         rsurface.batchelement3i_indexbuffer = NULL;
8108         rsurface.batchelement3i_bufferoffset = 0;
8109         rsurface.batchelement3s = NULL;
8110         rsurface.batchelement3s_indexbuffer = NULL;
8111         rsurface.batchelement3s_bufferoffset = 0;
8112         rsurface.passcolor4f = NULL;
8113         rsurface.passcolor4f_vertexbuffer = NULL;
8114         rsurface.passcolor4f_bufferoffset = 0;
8115
8116         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8117         {
8118                 if ((wantnormals || wanttangents) && !normal3f)
8119                 {
8120                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8121                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8122                 }
8123                 if (wanttangents && !svector3f)
8124                 {
8125                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8126                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8127                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8128                 }
8129         }
8130 }
8131
8132 float RSurf_FogPoint(const float *v)
8133 {
8134         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8135         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8136         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8137         float FogHeightFade = r_refdef.fogheightfade;
8138         float fogfrac;
8139         unsigned int fogmasktableindex;
8140         if (r_refdef.fogplaneviewabove)
8141                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8142         else
8143                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8144         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8145         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8146 }
8147
8148 float RSurf_FogVertex(const float *v)
8149 {
8150         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8151         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8152         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8153         float FogHeightFade = rsurface.fogheightfade;
8154         float fogfrac;
8155         unsigned int fogmasktableindex;
8156         if (r_refdef.fogplaneviewabove)
8157                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8158         else
8159                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8160         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8161         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8162 }
8163
8164 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8165 {
8166         int i;
8167         for (i = 0;i < numelements;i++)
8168                 outelement3i[i] = inelement3i[i] + adjust;
8169 }
8170
8171 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8172 extern cvar_t gl_vbo;
8173 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8174 {
8175         int deformindex;
8176         int firsttriangle;
8177         int numtriangles;
8178         int firstvertex;
8179         int endvertex;
8180         int numvertices;
8181         int surfacefirsttriangle;
8182         int surfacenumtriangles;
8183         int surfacefirstvertex;
8184         int surfaceendvertex;
8185         int surfacenumvertices;
8186         int batchnumvertices;
8187         int batchnumtriangles;
8188         int needsupdate;
8189         int i, j;
8190         qboolean gaps;
8191         qboolean dynamicvertex;
8192         float amplitude;
8193         float animpos;
8194         float scale;
8195         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8196         float waveparms[4];
8197         q3shaderinfo_deform_t *deform;
8198         const msurface_t *surface, *firstsurface;
8199         r_vertexmesh_t *vertexmesh;
8200         if (!texturenumsurfaces)
8201                 return;
8202         // find vertex range of this surface batch
8203         gaps = false;
8204         firstsurface = texturesurfacelist[0];
8205         firsttriangle = firstsurface->num_firsttriangle;
8206         batchnumvertices = 0;
8207         batchnumtriangles = 0;
8208         firstvertex = endvertex = firstsurface->num_firstvertex;
8209         for (i = 0;i < texturenumsurfaces;i++)
8210         {
8211                 surface = texturesurfacelist[i];
8212                 if (surface != firstsurface + i)
8213                         gaps = true;
8214                 surfacefirstvertex = surface->num_firstvertex;
8215                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8216                 surfacenumvertices = surface->num_vertices;
8217                 surfacenumtriangles = surface->num_triangles;
8218                 if (firstvertex > surfacefirstvertex)
8219                         firstvertex = surfacefirstvertex;
8220                 if (endvertex < surfaceendvertex)
8221                         endvertex = surfaceendvertex;
8222                 batchnumvertices += surfacenumvertices;
8223                 batchnumtriangles += surfacenumtriangles;
8224         }
8225
8226         // we now know the vertex range used, and if there are any gaps in it
8227         rsurface.batchfirstvertex = firstvertex;
8228         rsurface.batchnumvertices = endvertex - firstvertex;
8229         rsurface.batchfirsttriangle = firsttriangle;
8230         rsurface.batchnumtriangles = batchnumtriangles;
8231
8232         // this variable holds flags for which properties have been updated that
8233         // may require regenerating vertexmesh array...
8234         needsupdate = 0;
8235
8236         // check if any dynamic vertex processing must occur
8237         dynamicvertex = false;
8238
8239         // if there is a chance of animated vertex colors, it's a dynamic batch
8240         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8241         {
8242                 dynamicvertex = true;
8243                 batchneed |= BATCHNEED_NOGAPS;
8244                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8245         }
8246
8247         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8248         {
8249                 switch (deform->deform)
8250                 {
8251                 default:
8252                 case Q3DEFORM_PROJECTIONSHADOW:
8253                 case Q3DEFORM_TEXT0:
8254                 case Q3DEFORM_TEXT1:
8255                 case Q3DEFORM_TEXT2:
8256                 case Q3DEFORM_TEXT3:
8257                 case Q3DEFORM_TEXT4:
8258                 case Q3DEFORM_TEXT5:
8259                 case Q3DEFORM_TEXT6:
8260                 case Q3DEFORM_TEXT7:
8261                 case Q3DEFORM_NONE:
8262                         break;
8263                 case Q3DEFORM_AUTOSPRITE:
8264                         dynamicvertex = true;
8265                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8266                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8267                         break;
8268                 case Q3DEFORM_AUTOSPRITE2:
8269                         dynamicvertex = true;
8270                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8271                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8272                         break;
8273                 case Q3DEFORM_NORMAL:
8274                         dynamicvertex = true;
8275                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8276                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8277                         break;
8278                 case Q3DEFORM_WAVE:
8279                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8280                                 break; // if wavefunc is a nop, ignore this transform
8281                         dynamicvertex = true;
8282                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8283                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8284                         break;
8285                 case Q3DEFORM_BULGE:
8286                         dynamicvertex = true;
8287                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8288                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8289                         break;
8290                 case Q3DEFORM_MOVE:
8291                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8292                                 break; // if wavefunc is a nop, ignore this transform
8293                         dynamicvertex = true;
8294                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8295                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8296                         break;
8297                 }
8298         }
8299         switch(rsurface.texture->tcgen.tcgen)
8300         {
8301         default:
8302         case Q3TCGEN_TEXTURE:
8303                 break;
8304         case Q3TCGEN_LIGHTMAP:
8305                 dynamicvertex = true;
8306                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8307                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8308                 break;
8309         case Q3TCGEN_VECTOR:
8310                 dynamicvertex = true;
8311                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8312                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8313                 break;
8314         case Q3TCGEN_ENVIRONMENT:
8315                 dynamicvertex = true;
8316                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8317                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8318                 break;
8319         }
8320         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8321         {
8322                 dynamicvertex = true;
8323                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8324                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8325         }
8326
8327         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8328         {
8329                 dynamicvertex = true;
8330                 batchneed |= BATCHNEED_NOGAPS;
8331                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8332         }
8333
8334         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8335         {
8336                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8337                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8338                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8339                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8340                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8341                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8342                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8343         }
8344
8345         // when the model data has no vertex buffer (dynamic mesh), we need to
8346         // eliminate gaps
8347         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8348                 batchneed |= BATCHNEED_NOGAPS;
8349
8350         // if needsupdate, we have to do a dynamic vertex batch for sure
8351         if (needsupdate & batchneed)
8352                 dynamicvertex = true;
8353
8354         // see if we need to build vertexmesh from arrays
8355         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8356                 dynamicvertex = true;
8357
8358         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8359         // also some drivers strongly dislike firstvertex
8360         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8361                 dynamicvertex = true;
8362
8363         rsurface.batchvertex3f = rsurface.modelvertex3f;
8364         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8365         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8366         rsurface.batchsvector3f = rsurface.modelsvector3f;
8367         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8368         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8369         rsurface.batchtvector3f = rsurface.modeltvector3f;
8370         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8371         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8372         rsurface.batchnormal3f = rsurface.modelnormal3f;
8373         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8374         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8375         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8376         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8377         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8378         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8379         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8380         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8381         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8382         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8383         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8384         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8385         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8386         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8387         rsurface.batchelement3i = rsurface.modelelement3i;
8388         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8389         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8390         rsurface.batchelement3s = rsurface.modelelement3s;
8391         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8392         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8393
8394         // if any dynamic vertex processing has to occur in software, we copy the
8395         // entire surface list together before processing to rebase the vertices
8396         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8397         //
8398         // if any gaps exist and we do not have a static vertex buffer, we have to
8399         // copy the surface list together to avoid wasting upload bandwidth on the
8400         // vertices in the gaps.
8401         //
8402         // if gaps exist and we have a static vertex buffer, we still have to
8403         // combine the index buffer ranges into one dynamic index buffer.
8404         //
8405         // in all cases we end up with data that can be drawn in one call.
8406
8407         if (!dynamicvertex)
8408         {
8409                 // static vertex data, just set pointers...
8410                 rsurface.batchgeneratedvertex = false;
8411                 // if there are gaps, we want to build a combined index buffer,
8412                 // otherwise use the original static buffer with an appropriate offset
8413                 if (gaps)
8414                 {
8415                         // build a new triangle elements array for this batch
8416                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8417                         rsurface.batchfirsttriangle = 0;
8418                         numtriangles = 0;
8419                         for (i = 0;i < texturenumsurfaces;i++)
8420                         {
8421                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8422                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8423                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8424                                 numtriangles += surfacenumtriangles;
8425                         }
8426                         rsurface.batchelement3i_indexbuffer = NULL;
8427                         rsurface.batchelement3i_bufferoffset = 0;
8428                         rsurface.batchelement3s = NULL;
8429                         rsurface.batchelement3s_indexbuffer = NULL;
8430                         rsurface.batchelement3s_bufferoffset = 0;
8431                         if (endvertex <= 65536)
8432                         {
8433                                 // make a 16bit (unsigned short) index array if possible
8434                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8435                                 for (i = 0;i < numtriangles*3;i++)
8436                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8437                         }
8438                 }
8439                 return;
8440         }
8441
8442         // something needs software processing, do it for real...
8443         // we only directly handle separate array data in this case and then
8444         // generate interleaved data if needed...
8445         rsurface.batchgeneratedvertex = true;
8446
8447         // now copy the vertex data into a combined array and make an index array
8448         // (this is what Quake3 does all the time)
8449         //if (gaps || rsurface.batchfirstvertex)
8450         {
8451                 rsurface.batchvertex3fbuffer = NULL;
8452                 rsurface.batchvertexmesh = NULL;
8453                 rsurface.batchvertexmeshbuffer = NULL;
8454                 rsurface.batchvertex3f = NULL;
8455                 rsurface.batchvertex3f_vertexbuffer = NULL;
8456                 rsurface.batchvertex3f_bufferoffset = 0;
8457                 rsurface.batchsvector3f = NULL;
8458                 rsurface.batchsvector3f_vertexbuffer = NULL;
8459                 rsurface.batchsvector3f_bufferoffset = 0;
8460                 rsurface.batchtvector3f = NULL;
8461                 rsurface.batchtvector3f_vertexbuffer = NULL;
8462                 rsurface.batchtvector3f_bufferoffset = 0;
8463                 rsurface.batchnormal3f = NULL;
8464                 rsurface.batchnormal3f_vertexbuffer = NULL;
8465                 rsurface.batchnormal3f_bufferoffset = 0;
8466                 rsurface.batchlightmapcolor4f = NULL;
8467                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8468                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8469                 rsurface.batchtexcoordtexture2f = NULL;
8470                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8471                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8472                 rsurface.batchtexcoordlightmap2f = NULL;
8473                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8474                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8475                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8476                 rsurface.batchelement3i_indexbuffer = NULL;
8477                 rsurface.batchelement3i_bufferoffset = 0;
8478                 rsurface.batchelement3s = NULL;
8479                 rsurface.batchelement3s_indexbuffer = NULL;
8480                 rsurface.batchelement3s_bufferoffset = 0;
8481                 // we'll only be setting up certain arrays as needed
8482                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8483                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8484                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8485                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8486                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8487                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8488                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8489                 {
8490                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8491                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8492                 }
8493                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8494                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8495                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8496                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8497                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8498                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8499                 numvertices = 0;
8500                 numtriangles = 0;
8501                 for (i = 0;i < texturenumsurfaces;i++)
8502                 {
8503                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8504                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8505                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8506                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8507                         // copy only the data requested
8508                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8509                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8510                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8511                         {
8512                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8513                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8514                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8515                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8516                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8517                                 {
8518                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8519                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8520                                 }
8521                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8522                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8523                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8524                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8525                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8526                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8527                         }
8528                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8529                         numvertices += surfacenumvertices;
8530                         numtriangles += surfacenumtriangles;
8531                 }
8532
8533                 // generate a 16bit index array as well if possible
8534                 // (in general, dynamic batches fit)
8535                 if (numvertices <= 65536)
8536                 {
8537                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8538                         for (i = 0;i < numtriangles*3;i++)
8539                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8540                 }
8541
8542                 // since we've copied everything, the batch now starts at 0
8543                 rsurface.batchfirstvertex = 0;
8544                 rsurface.batchnumvertices = batchnumvertices;
8545                 rsurface.batchfirsttriangle = 0;
8546                 rsurface.batchnumtriangles = batchnumtriangles;
8547         }
8548
8549         // q1bsp surfaces rendered in vertex color mode have to have colors
8550         // calculated based on lightstyles
8551         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8552         {
8553                 // generate color arrays for the surfaces in this list
8554                 int c[4];
8555                 int scale;
8556                 int size3;
8557                 const int *offsets;
8558                 const unsigned char *lm;
8559                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8560                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8561                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8562                 numvertices = 0;
8563                 for (i = 0;i < texturenumsurfaces;i++)
8564                 {
8565                         surface = texturesurfacelist[i];
8566                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8567                         surfacenumvertices = surface->num_vertices;
8568                         if (surface->lightmapinfo->samples)
8569                         {
8570                                 for (j = 0;j < surfacenumvertices;j++)
8571                                 {
8572                                         lm = surface->lightmapinfo->samples + offsets[j];
8573                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8574                                         VectorScale(lm, scale, c);
8575                                         if (surface->lightmapinfo->styles[1] != 255)
8576                                         {
8577                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8578                                                 lm += size3;
8579                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8580                                                 VectorMA(c, scale, lm, c);
8581                                                 if (surface->lightmapinfo->styles[2] != 255)
8582                                                 {
8583                                                         lm += size3;
8584                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8585                                                         VectorMA(c, scale, lm, c);
8586                                                         if (surface->lightmapinfo->styles[3] != 255)
8587                                                         {
8588                                                                 lm += size3;
8589                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8590                                                                 VectorMA(c, scale, lm, c);
8591                                                         }
8592                                                 }
8593                                         }
8594                                         c[0] >>= 7;
8595                                         c[1] >>= 7;
8596                                         c[2] >>= 7;
8597                                         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);
8598                                         numvertices++;
8599                                 }
8600                         }
8601                         else
8602                         {
8603                                 for (j = 0;j < surfacenumvertices;j++)
8604                                 {
8605                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8606                                         numvertices++;
8607                                 }
8608                         }
8609                 }
8610         }
8611
8612         // if vertices are deformed (sprite flares and things in maps, possibly
8613         // water waves, bulges and other deformations), modify the copied vertices
8614         // in place
8615         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8616         {
8617                 switch (deform->deform)
8618                 {
8619                 default:
8620                 case Q3DEFORM_PROJECTIONSHADOW:
8621                 case Q3DEFORM_TEXT0:
8622                 case Q3DEFORM_TEXT1:
8623                 case Q3DEFORM_TEXT2:
8624                 case Q3DEFORM_TEXT3:
8625                 case Q3DEFORM_TEXT4:
8626                 case Q3DEFORM_TEXT5:
8627                 case Q3DEFORM_TEXT6:
8628                 case Q3DEFORM_TEXT7:
8629                 case Q3DEFORM_NONE:
8630                         break;
8631                 case Q3DEFORM_AUTOSPRITE:
8632                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8633                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8634                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8635                         VectorNormalize(newforward);
8636                         VectorNormalize(newright);
8637                         VectorNormalize(newup);
8638 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8639 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8640 //                      rsurface.batchvertex3f_bufferoffset = 0;
8641 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8642 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8643 //                      rsurface.batchsvector3f_bufferoffset = 0;
8644 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8645 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8646 //                      rsurface.batchtvector3f_bufferoffset = 0;
8647 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8648 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8649 //                      rsurface.batchnormal3f_bufferoffset = 0;
8650                         // a single autosprite surface can contain multiple sprites...
8651                         for (j = 0;j < batchnumvertices - 3;j += 4)
8652                         {
8653                                 VectorClear(center);
8654                                 for (i = 0;i < 4;i++)
8655                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8656                                 VectorScale(center, 0.25f, center);
8657                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8658                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8659                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8660                                 for (i = 0;i < 4;i++)
8661                                 {
8662                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8663                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8664                                 }
8665                         }
8666                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8667                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8668                         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);
8669                         break;
8670                 case Q3DEFORM_AUTOSPRITE2:
8671                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8672                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8673                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8674                         VectorNormalize(newforward);
8675                         VectorNormalize(newright);
8676                         VectorNormalize(newup);
8677 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8678 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8679 //                      rsurface.batchvertex3f_bufferoffset = 0;
8680                         {
8681                                 const float *v1, *v2;
8682                                 vec3_t start, end;
8683                                 float f, l;
8684                                 struct
8685                                 {
8686                                         float length2;
8687                                         const float *v1;
8688                                         const float *v2;
8689                                 }
8690                                 shortest[2];
8691                                 memset(shortest, 0, sizeof(shortest));
8692                                 // a single autosprite surface can contain multiple sprites...
8693                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8694                                 {
8695                                         VectorClear(center);
8696                                         for (i = 0;i < 4;i++)
8697                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8698                                         VectorScale(center, 0.25f, center);
8699                                         // find the two shortest edges, then use them to define the
8700                                         // axis vectors for rotating around the central axis
8701                                         for (i = 0;i < 6;i++)
8702                                         {
8703                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8704                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8705                                                 l = VectorDistance2(v1, v2);
8706                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8707                                                 if (v1[2] != v2[2])
8708                                                         l += (1.0f / 1024.0f);
8709                                                 if (shortest[0].length2 > l || i == 0)
8710                                                 {
8711                                                         shortest[1] = shortest[0];
8712                                                         shortest[0].length2 = l;
8713                                                         shortest[0].v1 = v1;
8714                                                         shortest[0].v2 = v2;
8715                                                 }
8716                                                 else if (shortest[1].length2 > l || i == 1)
8717                                                 {
8718                                                         shortest[1].length2 = l;
8719                                                         shortest[1].v1 = v1;
8720                                                         shortest[1].v2 = v2;
8721                                                 }
8722                                         }
8723                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8724                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8725                                         // this calculates the right vector from the shortest edge
8726                                         // and the up vector from the edge midpoints
8727                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8728                                         VectorNormalize(right);
8729                                         VectorSubtract(end, start, up);
8730                                         VectorNormalize(up);
8731                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8732                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8733                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8734                                         VectorNegate(forward, forward);
8735                                         VectorReflect(forward, 0, up, forward);
8736                                         VectorNormalize(forward);
8737                                         CrossProduct(up, forward, newright);
8738                                         VectorNormalize(newright);
8739                                         // rotate the quad around the up axis vector, this is made
8740                                         // especially easy by the fact we know the quad is flat,
8741                                         // so we only have to subtract the center position and
8742                                         // measure distance along the right vector, and then
8743                                         // multiply that by the newright vector and add back the
8744                                         // center position
8745                                         // we also need to subtract the old position to undo the
8746                                         // displacement from the center, which we do with a
8747                                         // DotProduct, the subtraction/addition of center is also
8748                                         // optimized into DotProducts here
8749                                         l = DotProduct(right, center);
8750                                         for (i = 0;i < 4;i++)
8751                                         {
8752                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8753                                                 f = DotProduct(right, v1) - l;
8754                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8755                                         }
8756                                 }
8757                         }
8758                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8759                         {
8760 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8761 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8762 //                              rsurface.batchnormal3f_bufferoffset = 0;
8763                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8764                         }
8765                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8766                         {
8767 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8768 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8769 //                              rsurface.batchsvector3f_bufferoffset = 0;
8770 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8771 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8772 //                              rsurface.batchtvector3f_bufferoffset = 0;
8773                                 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);
8774                         }
8775                         break;
8776                 case Q3DEFORM_NORMAL:
8777                         // deform the normals to make reflections wavey
8778                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8779                         rsurface.batchnormal3f_vertexbuffer = NULL;
8780                         rsurface.batchnormal3f_bufferoffset = 0;
8781                         for (j = 0;j < batchnumvertices;j++)
8782                         {
8783                                 float vertex[3];
8784                                 float *normal = rsurface.batchnormal3f + 3*j;
8785                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8786                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8787                                 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]);
8788                                 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]);
8789                                 VectorNormalize(normal);
8790                         }
8791                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8792                         {
8793 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8795 //                              rsurface.batchsvector3f_bufferoffset = 0;
8796 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8797 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8798 //                              rsurface.batchtvector3f_bufferoffset = 0;
8799                                 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);
8800                         }
8801                         break;
8802                 case Q3DEFORM_WAVE:
8803                         // deform vertex array to make wavey water and flags and such
8804                         waveparms[0] = deform->waveparms[0];
8805                         waveparms[1] = deform->waveparms[1];
8806                         waveparms[2] = deform->waveparms[2];
8807                         waveparms[3] = deform->waveparms[3];
8808                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8809                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8810                         // this is how a divisor of vertex influence on deformation
8811                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8812                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8813 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8814 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8815 //                      rsurface.batchvertex3f_bufferoffset = 0;
8816 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8817 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8818 //                      rsurface.batchnormal3f_bufferoffset = 0;
8819                         for (j = 0;j < batchnumvertices;j++)
8820                         {
8821                                 // if the wavefunc depends on time, evaluate it per-vertex
8822                                 if (waveparms[3])
8823                                 {
8824                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8825                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8826                                 }
8827                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8828                         }
8829                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8830                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8831                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8832                         {
8833 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8834 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8835 //                              rsurface.batchsvector3f_bufferoffset = 0;
8836 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8837 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8838 //                              rsurface.batchtvector3f_bufferoffset = 0;
8839                                 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);
8840                         }
8841                         break;
8842                 case Q3DEFORM_BULGE:
8843                         // deform vertex array to make the surface have moving bulges
8844 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8845 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8846 //                      rsurface.batchvertex3f_bufferoffset = 0;
8847 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8848 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8849 //                      rsurface.batchnormal3f_bufferoffset = 0;
8850                         for (j = 0;j < batchnumvertices;j++)
8851                         {
8852                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8853                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8854                         }
8855                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8856                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8857                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8858                         {
8859 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8860 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8861 //                              rsurface.batchsvector3f_bufferoffset = 0;
8862 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8863 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8864 //                              rsurface.batchtvector3f_bufferoffset = 0;
8865                                 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);
8866                         }
8867                         break;
8868                 case Q3DEFORM_MOVE:
8869                         // deform vertex array
8870                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8871                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8872                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8873                         VectorScale(deform->parms, scale, waveparms);
8874 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8875 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8876 //                      rsurface.batchvertex3f_bufferoffset = 0;
8877                         for (j = 0;j < batchnumvertices;j++)
8878                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8879                         break;
8880                 }
8881         }
8882
8883         // generate texcoords based on the chosen texcoord source
8884         switch(rsurface.texture->tcgen.tcgen)
8885         {
8886         default:
8887         case Q3TCGEN_TEXTURE:
8888                 break;
8889         case Q3TCGEN_LIGHTMAP:
8890 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8891 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8892 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8893                 if (rsurface.batchtexcoordlightmap2f)
8894                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8895                 break;
8896         case Q3TCGEN_VECTOR:
8897 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8898 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8899 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8900                 for (j = 0;j < batchnumvertices;j++)
8901                 {
8902                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8903                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8904                 }
8905                 break;
8906         case Q3TCGEN_ENVIRONMENT:
8907                 // make environment reflections using a spheremap
8908                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8909                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8910                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8911                 for (j = 0;j < batchnumvertices;j++)
8912                 {
8913                         // identical to Q3A's method, but executed in worldspace so
8914                         // carried models can be shiny too
8915
8916                         float viewer[3], d, reflected[3], worldreflected[3];
8917
8918                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8919                         // VectorNormalize(viewer);
8920
8921                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8922
8923                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8924                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8925                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8926                         // note: this is proportinal to viewer, so we can normalize later
8927
8928                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8929                         VectorNormalize(worldreflected);
8930
8931                         // note: this sphere map only uses world x and z!
8932                         // so positive and negative y will LOOK THE SAME.
8933                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8934                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8935                 }
8936                 break;
8937         }
8938         // the only tcmod that needs software vertex processing is turbulent, so
8939         // check for it here and apply the changes if needed
8940         // and we only support that as the first one
8941         // (handling a mixture of turbulent and other tcmods would be problematic
8942         //  without punting it entirely to a software path)
8943         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8944         {
8945                 amplitude = rsurface.texture->tcmods[0].parms[1];
8946                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8947 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8948 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8949 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8950                 for (j = 0;j < batchnumvertices;j++)
8951                 {
8952                         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);
8953                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8954                 }
8955         }
8956
8957         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8958         {
8959                 // convert the modified arrays to vertex structs
8960 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8961 //              rsurface.batchvertexmeshbuffer = NULL;
8962                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8963                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8964                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8965                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8966                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8967                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8968                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8969                 {
8970                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8971                         {
8972                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8973                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8974                         }
8975                 }
8976                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8977                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8978                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8979                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8980                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8981                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8982                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8983                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8984                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8985         }
8986 }
8987
8988 void RSurf_DrawBatch(void)
8989 {
8990         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8991         // through the pipeline, killing it earlier in the pipeline would have
8992         // per-surface overhead rather than per-batch overhead, so it's best to
8993         // reject it here, before it hits glDraw.
8994         if (rsurface.batchnumtriangles == 0)
8995                 return;
8996 #if 0
8997         // batch debugging code
8998         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8999         {
9000                 int i;
9001                 int j;
9002                 int c;
9003                 const int *e;
9004                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9005                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9006                 {
9007                         c = e[i];
9008                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9009                         {
9010                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9011                                 {
9012                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9013                                                 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);
9014                                         break;
9015                                 }
9016                         }
9017                 }
9018         }
9019 #endif
9020         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);
9021 }
9022
9023 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9024 {
9025         // pick the closest matching water plane
9026         int planeindex, vertexindex, bestplaneindex = -1;
9027         float d, bestd;
9028         vec3_t vert;
9029         const float *v;
9030         r_waterstate_waterplane_t *p;
9031         qboolean prepared = false;
9032         bestd = 0;
9033         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9034         {
9035                 if(p->camera_entity != rsurface.texture->camera_entity)
9036                         continue;
9037                 d = 0;
9038                 if(!prepared)
9039                 {
9040                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9041                         prepared = true;
9042                         if(rsurface.batchnumvertices == 0)
9043                                 break;
9044                 }
9045                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9046                 {
9047                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9048                         d += fabs(PlaneDiff(vert, &p->plane));
9049                 }
9050                 if (bestd > d || bestplaneindex < 0)
9051                 {
9052                         bestd = d;
9053                         bestplaneindex = planeindex;
9054                 }
9055         }
9056         return bestplaneindex;
9057         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9058         // this situation though, as it might be better to render single larger
9059         // batches with useless stuff (backface culled for example) than to
9060         // render multiple smaller batches
9061 }
9062
9063 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9064 {
9065         int i;
9066         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9067         rsurface.passcolor4f_vertexbuffer = 0;
9068         rsurface.passcolor4f_bufferoffset = 0;
9069         for (i = 0;i < rsurface.batchnumvertices;i++)
9070                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9071 }
9072
9073 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9074 {
9075         int i;
9076         float f;
9077         const float *v;
9078         const float *c;
9079         float *c2;
9080         if (rsurface.passcolor4f)
9081         {
9082                 // generate color arrays
9083                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9084                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9085                 rsurface.passcolor4f_vertexbuffer = 0;
9086                 rsurface.passcolor4f_bufferoffset = 0;
9087                 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)
9088                 {
9089                         f = RSurf_FogVertex(v);
9090                         c2[0] = c[0] * f;
9091                         c2[1] = c[1] * f;
9092                         c2[2] = c[2] * f;
9093                         c2[3] = c[3];
9094                 }
9095         }
9096         else
9097         {
9098                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9099                 rsurface.passcolor4f_vertexbuffer = 0;
9100                 rsurface.passcolor4f_bufferoffset = 0;
9101                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9102                 {
9103                         f = RSurf_FogVertex(v);
9104                         c2[0] = f;
9105                         c2[1] = f;
9106                         c2[2] = f;
9107                         c2[3] = 1;
9108                 }
9109         }
9110 }
9111
9112 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9113 {
9114         int i;
9115         float f;
9116         const float *v;
9117         const float *c;
9118         float *c2;
9119         if (!rsurface.passcolor4f)
9120                 return;
9121         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9122         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9123         rsurface.passcolor4f_vertexbuffer = 0;
9124         rsurface.passcolor4f_bufferoffset = 0;
9125         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)
9126         {
9127                 f = RSurf_FogVertex(v);
9128                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9129                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9130                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9131                 c2[3] = c[3];
9132         }
9133 }
9134
9135 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9136 {
9137         int i;
9138         const float *c;
9139         float *c2;
9140         if (!rsurface.passcolor4f)
9141                 return;
9142         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9143         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9144         rsurface.passcolor4f_vertexbuffer = 0;
9145         rsurface.passcolor4f_bufferoffset = 0;
9146         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9147         {
9148                 c2[0] = c[0] * r;
9149                 c2[1] = c[1] * g;
9150                 c2[2] = c[2] * b;
9151                 c2[3] = c[3] * a;
9152         }
9153 }
9154
9155 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9156 {
9157         int i;
9158         const float *c;
9159         float *c2;
9160         if (!rsurface.passcolor4f)
9161                 return;
9162         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9163         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9164         rsurface.passcolor4f_vertexbuffer = 0;
9165         rsurface.passcolor4f_bufferoffset = 0;
9166         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9167         {
9168                 c2[0] = c[0] + r_refdef.scene.ambient;
9169                 c2[1] = c[1] + r_refdef.scene.ambient;
9170                 c2[2] = c[2] + r_refdef.scene.ambient;
9171                 c2[3] = c[3];
9172         }
9173 }
9174
9175 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9176 {
9177         // TODO: optimize
9178         rsurface.passcolor4f = NULL;
9179         rsurface.passcolor4f_vertexbuffer = 0;
9180         rsurface.passcolor4f_bufferoffset = 0;
9181         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9182         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9183         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9184         GL_Color(r, g, b, a);
9185         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9186         RSurf_DrawBatch();
9187 }
9188
9189 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9190 {
9191         // TODO: optimize applyfog && applycolor case
9192         // just apply fog if necessary, and tint the fog color array if necessary
9193         rsurface.passcolor4f = NULL;
9194         rsurface.passcolor4f_vertexbuffer = 0;
9195         rsurface.passcolor4f_bufferoffset = 0;
9196         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9197         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9198         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9199         GL_Color(r, g, b, a);
9200         RSurf_DrawBatch();
9201 }
9202
9203 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9204 {
9205         // TODO: optimize
9206         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9207         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9208         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9209         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9210         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9211         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9212         GL_Color(r, g, b, a);
9213         RSurf_DrawBatch();
9214 }
9215
9216 static void RSurf_DrawBatch_GL11_ClampColor(void)
9217 {
9218         int i;
9219         const float *c1;
9220         float *c2;
9221         if (!rsurface.passcolor4f)
9222                 return;
9223         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9224         {
9225                 c2[0] = bound(0.0f, c1[0], 1.0f);
9226                 c2[1] = bound(0.0f, c1[1], 1.0f);
9227                 c2[2] = bound(0.0f, c1[2], 1.0f);
9228                 c2[3] = bound(0.0f, c1[3], 1.0f);
9229         }
9230 }
9231
9232 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9233 {
9234         int i;
9235         float f;
9236         const float *v;
9237         const float *n;
9238         float *c;
9239         //vec3_t eyedir;
9240
9241         // fake shading
9242         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9243         rsurface.passcolor4f_vertexbuffer = 0;
9244         rsurface.passcolor4f_bufferoffset = 0;
9245         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)
9246         {
9247                 f = -DotProduct(r_refdef.view.forward, n);
9248                 f = max(0, f);
9249                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9250                 f *= r_refdef.lightmapintensity;
9251                 Vector4Set(c, f, f, f, 1);
9252         }
9253 }
9254
9255 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9256 {
9257         RSurf_DrawBatch_GL11_ApplyFakeLight();
9258         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9259         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9260         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9261         GL_Color(r, g, b, a);
9262         RSurf_DrawBatch();
9263 }
9264
9265 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9266 {
9267         int i;
9268         float f;
9269         float alpha;
9270         const float *v;
9271         const float *n;
9272         float *c;
9273         vec3_t ambientcolor;
9274         vec3_t diffusecolor;
9275         vec3_t lightdir;
9276         // TODO: optimize
9277         // model lighting
9278         VectorCopy(rsurface.modellight_lightdir, lightdir);
9279         f = 0.5f * r_refdef.lightmapintensity;
9280         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9281         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9282         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9283         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9284         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9285         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9286         alpha = *a;
9287         if (VectorLength2(diffusecolor) > 0)
9288         {
9289                 // q3-style directional shading
9290                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9291                 rsurface.passcolor4f_vertexbuffer = 0;
9292                 rsurface.passcolor4f_bufferoffset = 0;
9293                 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)
9294                 {
9295                         if ((f = DotProduct(n, lightdir)) > 0)
9296                                 VectorMA(ambientcolor, f, diffusecolor, c);
9297                         else
9298                                 VectorCopy(ambientcolor, c);
9299                         c[3] = alpha;
9300                 }
9301                 *r = 1;
9302                 *g = 1;
9303                 *b = 1;
9304                 *a = 1;
9305                 *applycolor = false;
9306         }
9307         else
9308         {
9309                 *r = ambientcolor[0];
9310                 *g = ambientcolor[1];
9311                 *b = ambientcolor[2];
9312                 rsurface.passcolor4f = NULL;
9313                 rsurface.passcolor4f_vertexbuffer = 0;
9314                 rsurface.passcolor4f_bufferoffset = 0;
9315         }
9316 }
9317
9318 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9319 {
9320         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9321         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9322         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9323         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9324         GL_Color(r, g, b, a);
9325         RSurf_DrawBatch();
9326 }
9327
9328 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9329 {
9330         int i;
9331         float f;
9332         const float *v;
9333         float *c;
9334
9335         // fake shading
9336         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9337         rsurface.passcolor4f_vertexbuffer = 0;
9338         rsurface.passcolor4f_bufferoffset = 0;
9339
9340         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9341         {
9342                 f = 1 - RSurf_FogVertex(v);
9343                 c[0] = r;
9344                 c[1] = g;
9345                 c[2] = b;
9346                 c[3] = f * a;
9347         }
9348 }
9349
9350 void RSurf_SetupDepthAndCulling(void)
9351 {
9352         // submodels are biased to avoid z-fighting with world surfaces that they
9353         // may be exactly overlapping (avoids z-fighting artifacts on certain
9354         // doors and things in Quake maps)
9355         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9356         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9357         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9358         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9359 }
9360
9361 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9362 {
9363         // transparent sky would be ridiculous
9364         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9365                 return;
9366         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9367         skyrenderlater = true;
9368         RSurf_SetupDepthAndCulling();
9369         GL_DepthMask(true);
9370         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9371         // skymasking on them, and Quake3 never did sky masking (unlike
9372         // software Quake and software Quake2), so disable the sky masking
9373         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9374         // and skymasking also looks very bad when noclipping outside the
9375         // level, so don't use it then either.
9376         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9377         {
9378                 R_Mesh_ResetTextureState();
9379                 if (skyrendermasked)
9380                 {
9381                         R_SetupShader_DepthOrShadow();
9382                         // depth-only (masking)
9383                         GL_ColorMask(0,0,0,0);
9384                         // just to make sure that braindead drivers don't draw
9385                         // anything despite that colormask...
9386                         GL_BlendFunc(GL_ZERO, GL_ONE);
9387                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9388                         if (rsurface.batchvertex3fbuffer)
9389                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9390                         else
9391                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9392                 }
9393                 else
9394                 {
9395                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9396                         // fog sky
9397                         GL_BlendFunc(GL_ONE, GL_ZERO);
9398                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9399                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9400                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9401                 }
9402                 RSurf_DrawBatch();
9403                 if (skyrendermasked)
9404                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9405         }
9406         R_Mesh_ResetTextureState();
9407         GL_Color(1, 1, 1, 1);
9408 }
9409
9410 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9411 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9412 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9413 {
9414         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9415                 return;
9416         if (prepass)
9417         {
9418                 // render screenspace normalmap to texture
9419                 GL_DepthMask(true);
9420                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9421                 RSurf_DrawBatch();
9422                 return;
9423         }
9424
9425         // bind lightmap texture
9426
9427         // water/refraction/reflection/camera surfaces have to be handled specially
9428         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9429         {
9430                 int start, end, startplaneindex;
9431                 for (start = 0;start < texturenumsurfaces;start = end)
9432                 {
9433                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9434                         if(startplaneindex < 0)
9435                         {
9436                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9437                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9438                                 end = start + 1;
9439                                 continue;
9440                         }
9441                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9442                                 ;
9443                         // now that we have a batch using the same planeindex, render it
9444                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9445                         {
9446                                 // render water or distortion background
9447                                 GL_DepthMask(true);
9448                                 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));
9449                                 RSurf_DrawBatch();
9450                                 // blend surface on top
9451                                 GL_DepthMask(false);
9452                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9453                                 RSurf_DrawBatch();
9454                         }
9455                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9456                         {
9457                                 // render surface with reflection texture as input
9458                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9459                                 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));
9460                                 RSurf_DrawBatch();
9461                         }
9462                 }
9463                 return;
9464         }
9465
9466         // render surface batch normally
9467         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9468         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9469         RSurf_DrawBatch();
9470 }
9471
9472 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9473 {
9474         // OpenGL 1.3 path - anything not completely ancient
9475         qboolean applycolor;
9476         qboolean applyfog;
9477         int layerindex;
9478         const texturelayer_t *layer;
9479         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);
9480         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9481
9482         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9483         {
9484                 vec4_t layercolor;
9485                 int layertexrgbscale;
9486                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9487                 {
9488                         if (layerindex == 0)
9489                                 GL_AlphaTest(true);
9490                         else
9491                         {
9492                                 GL_AlphaTest(false);
9493                                 GL_DepthFunc(GL_EQUAL);
9494                         }
9495                 }
9496                 GL_DepthMask(layer->depthmask && writedepth);
9497                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9498                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9499                 {
9500                         layertexrgbscale = 4;
9501                         VectorScale(layer->color, 0.25f, layercolor);
9502                 }
9503                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9504                 {
9505                         layertexrgbscale = 2;
9506                         VectorScale(layer->color, 0.5f, layercolor);
9507                 }
9508                 else
9509                 {
9510                         layertexrgbscale = 1;
9511                         VectorScale(layer->color, 1.0f, layercolor);
9512                 }
9513                 layercolor[3] = layer->color[3];
9514                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9515                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9516                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9517                 switch (layer->type)
9518                 {
9519                 case TEXTURELAYERTYPE_LITTEXTURE:
9520                         // single-pass lightmapped texture with 2x rgbscale
9521                         R_Mesh_TexBind(0, r_texture_white);
9522                         R_Mesh_TexMatrix(0, NULL);
9523                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9524                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9525                         R_Mesh_TexBind(1, layer->texture);
9526                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9527                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9528                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9529                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9530                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9531                         else if (FAKELIGHT_ENABLED)
9532                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9533                         else if (rsurface.uselightmaptexture)
9534                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9535                         else
9536                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9537                         break;
9538                 case TEXTURELAYERTYPE_TEXTURE:
9539                         // singletexture unlit texture with transparency support
9540                         R_Mesh_TexBind(0, layer->texture);
9541                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9542                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9543                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9544                         R_Mesh_TexBind(1, 0);
9545                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9546                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9547                         break;
9548                 case TEXTURELAYERTYPE_FOG:
9549                         // singletexture fogging
9550                         if (layer->texture)
9551                         {
9552                                 R_Mesh_TexBind(0, layer->texture);
9553                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9554                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9555                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9556                         }
9557                         else
9558                         {
9559                                 R_Mesh_TexBind(0, 0);
9560                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9561                         }
9562                         R_Mesh_TexBind(1, 0);
9563                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9564                         // generate a color array for the fog pass
9565                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9566                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9567                         RSurf_DrawBatch();
9568                         break;
9569                 default:
9570                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9571                 }
9572         }
9573         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9574         {
9575                 GL_DepthFunc(GL_LEQUAL);
9576                 GL_AlphaTest(false);
9577         }
9578 }
9579
9580 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9581 {
9582         // OpenGL 1.1 - crusty old voodoo path
9583         qboolean applyfog;
9584         int layerindex;
9585         const texturelayer_t *layer;
9586         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);
9587         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9588
9589         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9590         {
9591                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9592                 {
9593                         if (layerindex == 0)
9594                                 GL_AlphaTest(true);
9595                         else
9596                         {
9597                                 GL_AlphaTest(false);
9598                                 GL_DepthFunc(GL_EQUAL);
9599                         }
9600                 }
9601                 GL_DepthMask(layer->depthmask && writedepth);
9602                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9603                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9604                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9605                 switch (layer->type)
9606                 {
9607                 case TEXTURELAYERTYPE_LITTEXTURE:
9608                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9609                         {
9610                                 // two-pass lit texture with 2x rgbscale
9611                                 // first the lightmap pass
9612                                 R_Mesh_TexBind(0, r_texture_white);
9613                                 R_Mesh_TexMatrix(0, NULL);
9614                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9615                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9616                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9617                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9618                                 else if (FAKELIGHT_ENABLED)
9619                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9620                                 else if (rsurface.uselightmaptexture)
9621                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9622                                 else
9623                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9624                                 // then apply the texture to it
9625                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9626                                 R_Mesh_TexBind(0, layer->texture);
9627                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9628                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9629                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9630                                 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);
9631                         }
9632                         else
9633                         {
9634                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9635                                 R_Mesh_TexBind(0, layer->texture);
9636                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9637                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9638                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9639                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9640                                         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);
9641                                 else
9642                                         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);
9643                         }
9644                         break;
9645                 case TEXTURELAYERTYPE_TEXTURE:
9646                         // singletexture unlit texture with transparency support
9647                         R_Mesh_TexBind(0, layer->texture);
9648                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9649                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9650                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9651                         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);
9652                         break;
9653                 case TEXTURELAYERTYPE_FOG:
9654                         // singletexture fogging
9655                         if (layer->texture)
9656                         {
9657                                 R_Mesh_TexBind(0, layer->texture);
9658                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9659                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9660                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9661                         }
9662                         else
9663                         {
9664                                 R_Mesh_TexBind(0, 0);
9665                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9666                         }
9667                         // generate a color array for the fog pass
9668                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9669                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9670                         RSurf_DrawBatch();
9671                         break;
9672                 default:
9673                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9674                 }
9675         }
9676         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9677         {
9678                 GL_DepthFunc(GL_LEQUAL);
9679                 GL_AlphaTest(false);
9680         }
9681 }
9682
9683 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9684 {
9685         int vi;
9686         int j;
9687         r_vertexgeneric_t *batchvertex;
9688         float c[4];
9689
9690 //      R_Mesh_ResetTextureState();
9691         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9692
9693         if(rsurface.texture && rsurface.texture->currentskinframe)
9694         {
9695                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9696                 c[3] *= rsurface.texture->currentalpha;
9697         }
9698         else
9699         {
9700                 c[0] = 1;
9701                 c[1] = 0;
9702                 c[2] = 1;
9703                 c[3] = 1;
9704         }
9705
9706         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9707         {
9708                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9709                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9710                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9711         }
9712
9713         // brighten it up (as texture value 127 means "unlit")
9714         c[0] *= 2 * r_refdef.view.colorscale;
9715         c[1] *= 2 * r_refdef.view.colorscale;
9716         c[2] *= 2 * r_refdef.view.colorscale;
9717
9718         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9719                 c[3] *= r_wateralpha.value;
9720
9721         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9722         {
9723                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9724                 GL_DepthMask(false);
9725         }
9726         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9727         {
9728                 GL_BlendFunc(GL_ONE, GL_ONE);
9729                 GL_DepthMask(false);
9730         }
9731         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9732         {
9733                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9734                 GL_DepthMask(false);
9735         }
9736         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9737         {
9738                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9739                 GL_DepthMask(false);
9740         }
9741         else
9742         {
9743                 GL_BlendFunc(GL_ONE, GL_ZERO);
9744                 GL_DepthMask(writedepth);
9745         }
9746
9747         if (r_showsurfaces.integer == 3)
9748         {
9749                 rsurface.passcolor4f = NULL;
9750
9751                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9752                 {
9753                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9754
9755                         rsurface.passcolor4f = NULL;
9756                         rsurface.passcolor4f_vertexbuffer = 0;
9757                         rsurface.passcolor4f_bufferoffset = 0;
9758                 }
9759                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9760                 {
9761                         qboolean applycolor = true;
9762                         float one = 1.0;
9763
9764                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9765
9766                         r_refdef.lightmapintensity = 1;
9767                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9768                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9769                 }
9770                 else if (FAKELIGHT_ENABLED)
9771                 {
9772                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9773
9774                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9775                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9776                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9777                 }
9778                 else
9779                 {
9780                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9781
9782                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9783                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9784                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9785                 }
9786
9787                 if(!rsurface.passcolor4f)
9788                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9789
9790                 RSurf_DrawBatch_GL11_ApplyAmbient();
9791                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9792                 if(r_refdef.fogenabled)
9793                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9794                 RSurf_DrawBatch_GL11_ClampColor();
9795
9796                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9797                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9798                 RSurf_DrawBatch();
9799         }
9800         else if (!r_refdef.view.showdebug)
9801         {
9802                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9803                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9804                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9805                 {
9806                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9807                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9808                 }
9809                 R_Mesh_PrepareVertices_Generic_Unlock();
9810                 RSurf_DrawBatch();
9811         }
9812         else if (r_showsurfaces.integer == 4)
9813         {
9814                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9815                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9816                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9817                 {
9818                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9819                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9820                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9821                 }
9822                 R_Mesh_PrepareVertices_Generic_Unlock();
9823                 RSurf_DrawBatch();
9824         }
9825         else if (r_showsurfaces.integer == 2)
9826         {
9827                 const int *e;
9828                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9829                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9830                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9831                 {
9832                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9833                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9834                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9835                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9836                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9837                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9838                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9839                 }
9840                 R_Mesh_PrepareVertices_Generic_Unlock();
9841                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9842         }
9843         else
9844         {
9845                 int texturesurfaceindex;
9846                 int k;
9847                 const msurface_t *surface;
9848                 float surfacecolor4f[4];
9849                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9850                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9851                 vi = 0;
9852                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9853                 {
9854                         surface = texturesurfacelist[texturesurfaceindex];
9855                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9856                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9857                         for (j = 0;j < surface->num_vertices;j++)
9858                         {
9859                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9860                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9861                                 vi++;
9862                         }
9863                 }
9864                 R_Mesh_PrepareVertices_Generic_Unlock();
9865                 RSurf_DrawBatch();
9866         }
9867 }
9868
9869 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9870 {
9871         CHECKGLERROR
9872         RSurf_SetupDepthAndCulling();
9873         if (r_showsurfaces.integer)
9874         {
9875                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9876                 return;
9877         }
9878         switch (vid.renderpath)
9879         {
9880         case RENDERPATH_GL20:
9881         case RENDERPATH_D3D9:
9882         case RENDERPATH_D3D10:
9883         case RENDERPATH_D3D11:
9884         case RENDERPATH_SOFT:
9885         case RENDERPATH_GLES2:
9886                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9887                 break;
9888         case RENDERPATH_GL13:
9889                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9890                 break;
9891         case RENDERPATH_GL11:
9892                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9893                 break;
9894         }
9895         CHECKGLERROR
9896 }
9897
9898 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9899 {
9900         CHECKGLERROR
9901         RSurf_SetupDepthAndCulling();
9902         if (r_showsurfaces.integer)
9903         {
9904                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9905                 return;
9906         }
9907         switch (vid.renderpath)
9908         {
9909         case RENDERPATH_GL20:
9910         case RENDERPATH_D3D9:
9911         case RENDERPATH_D3D10:
9912         case RENDERPATH_D3D11:
9913         case RENDERPATH_SOFT:
9914         case RENDERPATH_GLES2:
9915                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9916                 break;
9917         case RENDERPATH_GL13:
9918                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9919                 break;
9920         case RENDERPATH_GL11:
9921                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9922                 break;
9923         }
9924         CHECKGLERROR
9925 }
9926
9927 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9928 {
9929         int i, j;
9930         int texturenumsurfaces, endsurface;
9931         texture_t *texture;
9932         const msurface_t *surface;
9933 #define MAXBATCH_TRANSPARENTSURFACES 256
9934         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9935
9936         // if the model is static it doesn't matter what value we give for
9937         // wantnormals and wanttangents, so this logic uses only rules applicable
9938         // to a model, knowing that they are meaningless otherwise
9939         if (ent == r_refdef.scene.worldentity)
9940                 RSurf_ActiveWorldEntity();
9941         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9942                 RSurf_ActiveModelEntity(ent, false, false, false);
9943         else
9944         {
9945                 switch (vid.renderpath)
9946                 {
9947                 case RENDERPATH_GL20:
9948                 case RENDERPATH_D3D9:
9949                 case RENDERPATH_D3D10:
9950                 case RENDERPATH_D3D11:
9951                 case RENDERPATH_SOFT:
9952                 case RENDERPATH_GLES2:
9953                         RSurf_ActiveModelEntity(ent, true, true, false);
9954                         break;
9955                 case RENDERPATH_GL13:
9956                 case RENDERPATH_GL11:
9957                         RSurf_ActiveModelEntity(ent, true, false, false);
9958                         break;
9959                 }
9960         }
9961
9962         if (r_transparentdepthmasking.integer)
9963         {
9964                 qboolean setup = false;
9965                 for (i = 0;i < numsurfaces;i = j)
9966                 {
9967                         j = i + 1;
9968                         surface = rsurface.modelsurfaces + surfacelist[i];
9969                         texture = surface->texture;
9970                         rsurface.texture = R_GetCurrentTexture(texture);
9971                         rsurface.lightmaptexture = NULL;
9972                         rsurface.deluxemaptexture = NULL;
9973                         rsurface.uselightmaptexture = false;
9974                         // scan ahead until we find a different texture
9975                         endsurface = min(i + 1024, numsurfaces);
9976                         texturenumsurfaces = 0;
9977                         texturesurfacelist[texturenumsurfaces++] = surface;
9978                         for (;j < endsurface;j++)
9979                         {
9980                                 surface = rsurface.modelsurfaces + surfacelist[j];
9981                                 if (texture != surface->texture)
9982                                         break;
9983                                 texturesurfacelist[texturenumsurfaces++] = surface;
9984                         }
9985                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9986                                 continue;
9987                         // render the range of surfaces as depth
9988                         if (!setup)
9989                         {
9990                                 setup = true;
9991                                 GL_ColorMask(0,0,0,0);
9992                                 GL_Color(1,1,1,1);
9993                                 GL_DepthTest(true);
9994                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9995                                 GL_DepthMask(true);
9996 //                              R_Mesh_ResetTextureState();
9997                                 R_SetupShader_DepthOrShadow();
9998                         }
9999                         RSurf_SetupDepthAndCulling();
10000                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10001                         if (rsurface.batchvertex3fbuffer)
10002                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10003                         else
10004                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10005                         RSurf_DrawBatch();
10006                 }
10007                 if (setup)
10008                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10009         }
10010
10011         for (i = 0;i < numsurfaces;i = j)
10012         {
10013                 j = i + 1;
10014                 surface = rsurface.modelsurfaces + surfacelist[i];
10015                 texture = surface->texture;
10016                 rsurface.texture = R_GetCurrentTexture(texture);
10017                 // scan ahead until we find a different texture
10018                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10019                 texturenumsurfaces = 0;
10020                 texturesurfacelist[texturenumsurfaces++] = surface;
10021                 if(FAKELIGHT_ENABLED)
10022                 {
10023                         rsurface.lightmaptexture = NULL;
10024                         rsurface.deluxemaptexture = NULL;
10025                         rsurface.uselightmaptexture = false;
10026                         for (;j < endsurface;j++)
10027                         {
10028                                 surface = rsurface.modelsurfaces + surfacelist[j];
10029                                 if (texture != surface->texture)
10030                                         break;
10031                                 texturesurfacelist[texturenumsurfaces++] = surface;
10032                         }
10033                 }
10034                 else
10035                 {
10036                         rsurface.lightmaptexture = surface->lightmaptexture;
10037                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10038                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10039                         for (;j < endsurface;j++)
10040                         {
10041                                 surface = rsurface.modelsurfaces + surfacelist[j];
10042                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10043                                         break;
10044                                 texturesurfacelist[texturenumsurfaces++] = surface;
10045                         }
10046                 }
10047                 // render the range of surfaces
10048                 if (ent == r_refdef.scene.worldentity)
10049                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10050                 else
10051                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10052         }
10053         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10054 }
10055
10056 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10057 {
10058         // transparent surfaces get pushed off into the transparent queue
10059         int surfacelistindex;
10060         const msurface_t *surface;
10061         vec3_t tempcenter, center;
10062         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10063         {
10064                 surface = texturesurfacelist[surfacelistindex];
10065                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10066                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10067                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10068                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10069                 if (queueentity->transparent_offset) // transparent offset
10070                 {
10071                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10072                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10073                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10074                 }
10075                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10076         }
10077 }
10078
10079 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10080 {
10081         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10082                 return;
10083         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10084                 return;
10085         RSurf_SetupDepthAndCulling();
10086         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10087         if (rsurface.batchvertex3fbuffer)
10088                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10089         else
10090                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10091         RSurf_DrawBatch();
10092 }
10093
10094 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10095 {
10096         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10097         CHECKGLERROR
10098         if (depthonly)
10099                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10100         else if (prepass)
10101         {
10102                 if (!rsurface.texture->currentnumlayers)
10103                         return;
10104                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10105                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10106                 else
10107                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10108         }
10109         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10110                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10111         else if (!rsurface.texture->currentnumlayers)
10112                 return;
10113         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10114         {
10115                 // in the deferred case, transparent surfaces were queued during prepass
10116                 if (!r_shadow_usingdeferredprepass)
10117                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10118         }
10119         else
10120         {
10121                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10122                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10123         }
10124         CHECKGLERROR
10125 }
10126
10127 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10128 {
10129         int i, j;
10130         texture_t *texture;
10131         R_FrameData_SetMark();
10132         // break the surface list down into batches by texture and use of lightmapping
10133         for (i = 0;i < numsurfaces;i = j)
10134         {
10135                 j = i + 1;
10136                 // texture is the base texture pointer, rsurface.texture is the
10137                 // current frame/skin the texture is directing us to use (for example
10138                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10139                 // use skin 1 instead)
10140                 texture = surfacelist[i]->texture;
10141                 rsurface.texture = R_GetCurrentTexture(texture);
10142                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10143                 {
10144                         // if this texture is not the kind we want, skip ahead to the next one
10145                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10146                                 ;
10147                         continue;
10148                 }
10149                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10150                 {
10151                         rsurface.lightmaptexture = NULL;
10152                         rsurface.deluxemaptexture = NULL;
10153                         rsurface.uselightmaptexture = false;
10154                         // simply scan ahead until we find a different texture or lightmap state
10155                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10156                                 ;
10157                 }
10158                 else
10159                 {
10160                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10161                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10162                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10163                         // simply scan ahead until we find a different texture or lightmap state
10164                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10165                                 ;
10166                 }
10167                 // render the range of surfaces
10168                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10169         }
10170         R_FrameData_ReturnToMark();
10171 }
10172
10173 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10174 {
10175         CHECKGLERROR
10176         if (depthonly)
10177                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10178         else if (prepass)
10179         {
10180                 if (!rsurface.texture->currentnumlayers)
10181                         return;
10182                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10183                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10184                 else
10185                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10186         }
10187         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10188                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10189         else if (!rsurface.texture->currentnumlayers)
10190                 return;
10191         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10192         {
10193                 // in the deferred case, transparent surfaces were queued during prepass
10194                 if (!r_shadow_usingdeferredprepass)
10195                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10196         }
10197         else
10198         {
10199                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10200                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10201         }
10202         CHECKGLERROR
10203 }
10204
10205 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10206 {
10207         int i, j;
10208         texture_t *texture;
10209         R_FrameData_SetMark();
10210         // break the surface list down into batches by texture and use of lightmapping
10211         for (i = 0;i < numsurfaces;i = j)
10212         {
10213                 j = i + 1;
10214                 // texture is the base texture pointer, rsurface.texture is the
10215                 // current frame/skin the texture is directing us to use (for example
10216                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10217                 // use skin 1 instead)
10218                 texture = surfacelist[i]->texture;
10219                 rsurface.texture = R_GetCurrentTexture(texture);
10220                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10221                 {
10222                         // if this texture is not the kind we want, skip ahead to the next one
10223                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10224                                 ;
10225                         continue;
10226                 }
10227                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10228                 {
10229                         rsurface.lightmaptexture = NULL;
10230                         rsurface.deluxemaptexture = NULL;
10231                         rsurface.uselightmaptexture = false;
10232                         // simply scan ahead until we find a different texture or lightmap state
10233                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10234                                 ;
10235                 }
10236                 else
10237                 {
10238                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10239                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10240                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10241                         // simply scan ahead until we find a different texture or lightmap state
10242                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10243                                 ;
10244                 }
10245                 // render the range of surfaces
10246                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10247         }
10248         R_FrameData_ReturnToMark();
10249 }
10250
10251 float locboxvertex3f[6*4*3] =
10252 {
10253         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10254         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10255         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10256         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10257         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10258         1,0,0, 0,0,0, 0,1,0, 1,1,0
10259 };
10260
10261 unsigned short locboxelements[6*2*3] =
10262 {
10263          0, 1, 2, 0, 2, 3,
10264          4, 5, 6, 4, 6, 7,
10265          8, 9,10, 8,10,11,
10266         12,13,14, 12,14,15,
10267         16,17,18, 16,18,19,
10268         20,21,22, 20,22,23
10269 };
10270
10271 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10272 {
10273         int i, j;
10274         cl_locnode_t *loc = (cl_locnode_t *)ent;
10275         vec3_t mins, size;
10276         float vertex3f[6*4*3];
10277         CHECKGLERROR
10278         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10279         GL_DepthMask(false);
10280         GL_DepthRange(0, 1);
10281         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10282         GL_DepthTest(true);
10283         GL_CullFace(GL_NONE);
10284         R_EntityMatrix(&identitymatrix);
10285
10286 //      R_Mesh_ResetTextureState();
10287
10288         i = surfacelist[0];
10289         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10290                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10291                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10292                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10293
10294         if (VectorCompare(loc->mins, loc->maxs))
10295         {
10296                 VectorSet(size, 2, 2, 2);
10297                 VectorMA(loc->mins, -0.5f, size, mins);
10298         }
10299         else
10300         {
10301                 VectorCopy(loc->mins, mins);
10302                 VectorSubtract(loc->maxs, loc->mins, size);
10303         }
10304
10305         for (i = 0;i < 6*4*3;)
10306                 for (j = 0;j < 3;j++, i++)
10307                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10308
10309         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10310         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10311         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10312 }
10313
10314 void R_DrawLocs(void)
10315 {
10316         int index;
10317         cl_locnode_t *loc, *nearestloc;
10318         vec3_t center;
10319         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10320         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10321         {
10322                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10323                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10324         }
10325 }
10326
10327 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10328 {
10329         if (decalsystem->decals)
10330                 Mem_Free(decalsystem->decals);
10331         memset(decalsystem, 0, sizeof(*decalsystem));
10332 }
10333
10334 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)
10335 {
10336         tridecal_t *decal;
10337         tridecal_t *decals;
10338         int i;
10339
10340         // expand or initialize the system
10341         if (decalsystem->maxdecals <= decalsystem->numdecals)
10342         {
10343                 decalsystem_t old = *decalsystem;
10344                 qboolean useshortelements;
10345                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10346                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10347                 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)));
10348                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10349                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10350                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10351                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10352                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10353                 if (decalsystem->numdecals)
10354                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10355                 if (old.decals)
10356                         Mem_Free(old.decals);
10357                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10358                         decalsystem->element3i[i] = i;
10359                 if (useshortelements)
10360                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10361                                 decalsystem->element3s[i] = i;
10362         }
10363
10364         // grab a decal and search for another free slot for the next one
10365         decals = decalsystem->decals;
10366         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10367         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10368                 ;
10369         decalsystem->freedecal = i;
10370         if (decalsystem->numdecals <= i)
10371                 decalsystem->numdecals = i + 1;
10372
10373         // initialize the decal
10374         decal->lived = 0;
10375         decal->triangleindex = triangleindex;
10376         decal->surfaceindex = surfaceindex;
10377         decal->decalsequence = decalsequence;
10378         decal->color4f[0][0] = c0[0];
10379         decal->color4f[0][1] = c0[1];
10380         decal->color4f[0][2] = c0[2];
10381         decal->color4f[0][3] = 1;
10382         decal->color4f[1][0] = c1[0];
10383         decal->color4f[1][1] = c1[1];
10384         decal->color4f[1][2] = c1[2];
10385         decal->color4f[1][3] = 1;
10386         decal->color4f[2][0] = c2[0];
10387         decal->color4f[2][1] = c2[1];
10388         decal->color4f[2][2] = c2[2];
10389         decal->color4f[2][3] = 1;
10390         decal->vertex3f[0][0] = v0[0];
10391         decal->vertex3f[0][1] = v0[1];
10392         decal->vertex3f[0][2] = v0[2];
10393         decal->vertex3f[1][0] = v1[0];
10394         decal->vertex3f[1][1] = v1[1];
10395         decal->vertex3f[1][2] = v1[2];
10396         decal->vertex3f[2][0] = v2[0];
10397         decal->vertex3f[2][1] = v2[1];
10398         decal->vertex3f[2][2] = v2[2];
10399         decal->texcoord2f[0][0] = t0[0];
10400         decal->texcoord2f[0][1] = t0[1];
10401         decal->texcoord2f[1][0] = t1[0];
10402         decal->texcoord2f[1][1] = t1[1];
10403         decal->texcoord2f[2][0] = t2[0];
10404         decal->texcoord2f[2][1] = t2[1];
10405 }
10406
10407 extern cvar_t cl_decals_bias;
10408 extern cvar_t cl_decals_models;
10409 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10410 // baseparms, parms, temps
10411 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)
10412 {
10413         int cornerindex;
10414         int index;
10415         float v[9][3];
10416         const float *vertex3f;
10417         const float *normal3f;
10418         int numpoints;
10419         float points[2][9][3];
10420         float temp[3];
10421         float tc[9][2];
10422         float f;
10423         float c[9][4];
10424         const int *e;
10425
10426         e = rsurface.modelelement3i + 3*triangleindex;
10427
10428         vertex3f = rsurface.modelvertex3f;
10429         normal3f = rsurface.modelnormal3f;
10430
10431         if (normal3f)
10432         {
10433                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10434                 {
10435                         index = 3*e[cornerindex];
10436                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10437                 }
10438         }
10439         else
10440         {
10441                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10442                 {
10443                         index = 3*e[cornerindex];
10444                         VectorCopy(vertex3f + index, v[cornerindex]);
10445                 }
10446         }
10447
10448         // cull backfaces
10449         //TriangleNormal(v[0], v[1], v[2], normal);
10450         //if (DotProduct(normal, localnormal) < 0.0f)
10451         //      continue;
10452         // clip by each of the box planes formed from the projection matrix
10453         // if anything survives, we emit the decal
10454         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]);
10455         if (numpoints < 3)
10456                 return;
10457         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]);
10458         if (numpoints < 3)
10459                 return;
10460         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]);
10461         if (numpoints < 3)
10462                 return;
10463         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]);
10464         if (numpoints < 3)
10465                 return;
10466         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]);
10467         if (numpoints < 3)
10468                 return;
10469         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]);
10470         if (numpoints < 3)
10471                 return;
10472         // some part of the triangle survived, so we have to accept it...
10473         if (dynamic)
10474         {
10475                 // dynamic always uses the original triangle
10476                 numpoints = 3;
10477                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10478                 {
10479                         index = 3*e[cornerindex];
10480                         VectorCopy(vertex3f + index, v[cornerindex]);
10481                 }
10482         }
10483         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10484         {
10485                 // convert vertex positions to texcoords
10486                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10487                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10488                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10489                 // calculate distance fade from the projection origin
10490                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10491                 f = bound(0.0f, f, 1.0f);
10492                 c[cornerindex][0] = r * f;
10493                 c[cornerindex][1] = g * f;
10494                 c[cornerindex][2] = b * f;
10495                 c[cornerindex][3] = 1.0f;
10496                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10497         }
10498         if (dynamic)
10499                 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);
10500         else
10501                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10502                         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);
10503 }
10504 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)
10505 {
10506         matrix4x4_t projection;
10507         decalsystem_t *decalsystem;
10508         qboolean dynamic;
10509         dp_model_t *model;
10510         const msurface_t *surface;
10511         const msurface_t *surfaces;
10512         const int *surfacelist;
10513         const texture_t *texture;
10514         int numtriangles;
10515         int numsurfacelist;
10516         int surfacelistindex;
10517         int surfaceindex;
10518         int triangleindex;
10519         float localorigin[3];
10520         float localnormal[3];
10521         float localmins[3];
10522         float localmaxs[3];
10523         float localsize;
10524         //float normal[3];
10525         float planes[6][4];
10526         float angles[3];
10527         bih_t *bih;
10528         int bih_triangles_count;
10529         int bih_triangles[256];
10530         int bih_surfaces[256];
10531
10532         decalsystem = &ent->decalsystem;
10533         model = ent->model;
10534         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10535         {
10536                 R_DecalSystem_Reset(&ent->decalsystem);
10537                 return;
10538         }
10539
10540         if (!model->brush.data_leafs && !cl_decals_models.integer)
10541         {
10542                 if (decalsystem->model)
10543                         R_DecalSystem_Reset(decalsystem);
10544                 return;
10545         }
10546
10547         if (decalsystem->model != model)
10548                 R_DecalSystem_Reset(decalsystem);
10549         decalsystem->model = model;
10550
10551         RSurf_ActiveModelEntity(ent, true, false, false);
10552
10553         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10554         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10555         VectorNormalize(localnormal);
10556         localsize = worldsize*rsurface.inversematrixscale;
10557         localmins[0] = localorigin[0] - localsize;
10558         localmins[1] = localorigin[1] - localsize;
10559         localmins[2] = localorigin[2] - localsize;
10560         localmaxs[0] = localorigin[0] + localsize;
10561         localmaxs[1] = localorigin[1] + localsize;
10562         localmaxs[2] = localorigin[2] + localsize;
10563
10564         //VectorCopy(localnormal, planes[4]);
10565         //VectorVectors(planes[4], planes[2], planes[0]);
10566         AnglesFromVectors(angles, localnormal, NULL, false);
10567         AngleVectors(angles, planes[0], planes[2], planes[4]);
10568         VectorNegate(planes[0], planes[1]);
10569         VectorNegate(planes[2], planes[3]);
10570         VectorNegate(planes[4], planes[5]);
10571         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10572         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10573         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10574         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10575         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10576         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10577
10578 #if 1
10579 // works
10580 {
10581         matrix4x4_t forwardprojection;
10582         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10583         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10584 }
10585 #else
10586 // broken
10587 {
10588         float projectionvector[4][3];
10589         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10590         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10591         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10592         projectionvector[0][0] = planes[0][0] * ilocalsize;
10593         projectionvector[0][1] = planes[1][0] * ilocalsize;
10594         projectionvector[0][2] = planes[2][0] * ilocalsize;
10595         projectionvector[1][0] = planes[0][1] * ilocalsize;
10596         projectionvector[1][1] = planes[1][1] * ilocalsize;
10597         projectionvector[1][2] = planes[2][1] * ilocalsize;
10598         projectionvector[2][0] = planes[0][2] * ilocalsize;
10599         projectionvector[2][1] = planes[1][2] * ilocalsize;
10600         projectionvector[2][2] = planes[2][2] * ilocalsize;
10601         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10602         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10603         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10604         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10605 }
10606 #endif
10607
10608         dynamic = model->surfmesh.isanimated;
10609         numsurfacelist = model->nummodelsurfaces;
10610         surfacelist = model->sortedmodelsurfaces;
10611         surfaces = model->data_surfaces;
10612
10613         bih = NULL;
10614         bih_triangles_count = -1;
10615         if(!dynamic)
10616         {
10617                 if(model->render_bih.numleafs)
10618                         bih = &model->render_bih;
10619                 else if(model->collision_bih.numleafs)
10620                         bih = &model->collision_bih;
10621         }
10622         if(bih)
10623                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10624         if(bih_triangles_count == 0)
10625                 return;
10626         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10627                 return;
10628         if(bih_triangles_count > 0)
10629         {
10630                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10631                 {
10632                         surfaceindex = bih_surfaces[triangleindex];
10633                         surface = surfaces + surfaceindex;
10634                         texture = surface->texture;
10635                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10636                                 continue;
10637                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10638                                 continue;
10639                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10640                 }
10641         }
10642         else
10643         {
10644                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10645                 {
10646                         surfaceindex = surfacelist[surfacelistindex];
10647                         surface = surfaces + surfaceindex;
10648                         // check cull box first because it rejects more than any other check
10649                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10650                                 continue;
10651                         // skip transparent surfaces
10652                         texture = surface->texture;
10653                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10654                                 continue;
10655                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10656                                 continue;
10657                         numtriangles = surface->num_triangles;
10658                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10659                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10660                 }
10661         }
10662 }
10663
10664 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10665 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)
10666 {
10667         int renderentityindex;
10668         float worldmins[3];
10669         float worldmaxs[3];
10670         entity_render_t *ent;
10671
10672         if (!cl_decals_newsystem.integer)
10673                 return;
10674
10675         worldmins[0] = worldorigin[0] - worldsize;
10676         worldmins[1] = worldorigin[1] - worldsize;
10677         worldmins[2] = worldorigin[2] - worldsize;
10678         worldmaxs[0] = worldorigin[0] + worldsize;
10679         worldmaxs[1] = worldorigin[1] + worldsize;
10680         worldmaxs[2] = worldorigin[2] + worldsize;
10681
10682         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10683
10684         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10685         {
10686                 ent = r_refdef.scene.entities[renderentityindex];
10687                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10688                         continue;
10689
10690                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10691         }
10692 }
10693
10694 typedef struct r_decalsystem_splatqueue_s
10695 {
10696         vec3_t worldorigin;
10697         vec3_t worldnormal;
10698         float color[4];
10699         float tcrange[4];
10700         float worldsize;
10701         int decalsequence;
10702 }
10703 r_decalsystem_splatqueue_t;
10704
10705 int r_decalsystem_numqueued = 0;
10706 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10707
10708 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)
10709 {
10710         r_decalsystem_splatqueue_t *queue;
10711
10712         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10713                 return;
10714
10715         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10716         VectorCopy(worldorigin, queue->worldorigin);
10717         VectorCopy(worldnormal, queue->worldnormal);
10718         Vector4Set(queue->color, r, g, b, a);
10719         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10720         queue->worldsize = worldsize;
10721         queue->decalsequence = cl.decalsequence++;
10722 }
10723
10724 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10725 {
10726         int i;
10727         r_decalsystem_splatqueue_t *queue;
10728
10729         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10730                 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);
10731         r_decalsystem_numqueued = 0;
10732 }
10733
10734 extern cvar_t cl_decals_max;
10735 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10736 {
10737         int i;
10738         decalsystem_t *decalsystem = &ent->decalsystem;
10739         int numdecals;
10740         int killsequence;
10741         tridecal_t *decal;
10742         float frametime;
10743         float lifetime;
10744
10745         if (!decalsystem->numdecals)
10746                 return;
10747
10748         if (r_showsurfaces.integer)
10749                 return;
10750
10751         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10752         {
10753                 R_DecalSystem_Reset(decalsystem);
10754                 return;
10755         }
10756
10757         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10758         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10759
10760         if (decalsystem->lastupdatetime)
10761                 frametime = (cl.time - decalsystem->lastupdatetime);
10762         else
10763                 frametime = 0;
10764         decalsystem->lastupdatetime = cl.time;
10765         decal = decalsystem->decals;
10766         numdecals = decalsystem->numdecals;
10767
10768         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10769         {
10770                 if (decal->color4f[0][3])
10771                 {
10772                         decal->lived += frametime;
10773                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10774                         {
10775                                 memset(decal, 0, sizeof(*decal));
10776                                 if (decalsystem->freedecal > i)
10777                                         decalsystem->freedecal = i;
10778                         }
10779                 }
10780         }
10781         decal = decalsystem->decals;
10782         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10783                 numdecals--;
10784
10785         // collapse the array by shuffling the tail decals into the gaps
10786         for (;;)
10787         {
10788                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10789                         decalsystem->freedecal++;
10790                 if (decalsystem->freedecal == numdecals)
10791                         break;
10792                 decal[decalsystem->freedecal] = decal[--numdecals];
10793         }
10794
10795         decalsystem->numdecals = numdecals;
10796
10797         if (numdecals <= 0)
10798         {
10799                 // if there are no decals left, reset decalsystem
10800                 R_DecalSystem_Reset(decalsystem);
10801         }
10802 }
10803
10804 extern skinframe_t *decalskinframe;
10805 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10806 {
10807         int i;
10808         decalsystem_t *decalsystem = &ent->decalsystem;
10809         int numdecals;
10810         tridecal_t *decal;
10811         float faderate;
10812         float alpha;
10813         float *v3f;
10814         float *c4f;
10815         float *t2f;
10816         const int *e;
10817         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10818         int numtris = 0;
10819
10820         numdecals = decalsystem->numdecals;
10821         if (!numdecals)
10822                 return;
10823
10824         if (r_showsurfaces.integer)
10825                 return;
10826
10827         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10828         {
10829                 R_DecalSystem_Reset(decalsystem);
10830                 return;
10831         }
10832
10833         // if the model is static it doesn't matter what value we give for
10834         // wantnormals and wanttangents, so this logic uses only rules applicable
10835         // to a model, knowing that they are meaningless otherwise
10836         if (ent == r_refdef.scene.worldentity)
10837                 RSurf_ActiveWorldEntity();
10838         else
10839                 RSurf_ActiveModelEntity(ent, false, false, false);
10840
10841         decalsystem->lastupdatetime = cl.time;
10842         decal = decalsystem->decals;
10843
10844         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10845
10846         // update vertex positions for animated models
10847         v3f = decalsystem->vertex3f;
10848         c4f = decalsystem->color4f;
10849         t2f = decalsystem->texcoord2f;
10850         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10851         {
10852                 if (!decal->color4f[0][3])
10853                         continue;
10854
10855                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10856                         continue;
10857
10858                 // update color values for fading decals
10859                 if (decal->lived >= cl_decals_time.value)
10860                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10861                 else
10862                         alpha = 1.0f;
10863
10864                 c4f[ 0] = decal->color4f[0][0] * alpha;
10865                 c4f[ 1] = decal->color4f[0][1] * alpha;
10866                 c4f[ 2] = decal->color4f[0][2] * alpha;
10867                 c4f[ 3] = 1;
10868                 c4f[ 4] = decal->color4f[1][0] * alpha;
10869                 c4f[ 5] = decal->color4f[1][1] * alpha;
10870                 c4f[ 6] = decal->color4f[1][2] * alpha;
10871                 c4f[ 7] = 1;
10872                 c4f[ 8] = decal->color4f[2][0] * alpha;
10873                 c4f[ 9] = decal->color4f[2][1] * alpha;
10874                 c4f[10] = decal->color4f[2][2] * alpha;
10875                 c4f[11] = 1;
10876
10877                 t2f[0] = decal->texcoord2f[0][0];
10878                 t2f[1] = decal->texcoord2f[0][1];
10879                 t2f[2] = decal->texcoord2f[1][0];
10880                 t2f[3] = decal->texcoord2f[1][1];
10881                 t2f[4] = decal->texcoord2f[2][0];
10882                 t2f[5] = decal->texcoord2f[2][1];
10883
10884                 // update vertex positions for animated models
10885                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10886                 {
10887                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10888                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10889                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10890                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10891                 }
10892                 else
10893                 {
10894                         VectorCopy(decal->vertex3f[0], v3f);
10895                         VectorCopy(decal->vertex3f[1], v3f + 3);
10896                         VectorCopy(decal->vertex3f[2], v3f + 6);
10897                 }
10898
10899                 if (r_refdef.fogenabled)
10900                 {
10901                         alpha = RSurf_FogVertex(v3f);
10902                         VectorScale(c4f, alpha, c4f);
10903                         alpha = RSurf_FogVertex(v3f + 3);
10904                         VectorScale(c4f + 4, alpha, c4f + 4);
10905                         alpha = RSurf_FogVertex(v3f + 6);
10906                         VectorScale(c4f + 8, alpha, c4f + 8);
10907                 }
10908
10909                 v3f += 9;
10910                 c4f += 12;
10911                 t2f += 6;
10912                 numtris++;
10913         }
10914
10915         if (numtris > 0)
10916         {
10917                 r_refdef.stats.drawndecals += numtris;
10918
10919                 // now render the decals all at once
10920                 // (this assumes they all use one particle font texture!)
10921                 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);
10922 //              R_Mesh_ResetTextureState();
10923                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10924                 GL_DepthMask(false);
10925                 GL_DepthRange(0, 1);
10926                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10927                 GL_DepthTest(true);
10928                 GL_CullFace(GL_NONE);
10929                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10930                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10931                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10932         }
10933 }
10934
10935 static void R_DrawModelDecals(void)
10936 {
10937         int i, numdecals;
10938
10939         // fade faster when there are too many decals
10940         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10941         for (i = 0;i < r_refdef.scene.numentities;i++)
10942                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10943
10944         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10945         for (i = 0;i < r_refdef.scene.numentities;i++)
10946                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10947                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10948
10949         R_DecalSystem_ApplySplatEntitiesQueue();
10950
10951         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10952         for (i = 0;i < r_refdef.scene.numentities;i++)
10953                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10954
10955         r_refdef.stats.totaldecals += numdecals;
10956
10957         if (r_showsurfaces.integer)
10958                 return;
10959
10960         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10961
10962         for (i = 0;i < r_refdef.scene.numentities;i++)
10963         {
10964                 if (!r_refdef.viewcache.entityvisible[i])
10965                         continue;
10966                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10967                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10968         }
10969 }
10970
10971 extern cvar_t mod_collision_bih;
10972 void R_DrawDebugModel(void)
10973 {
10974         entity_render_t *ent = rsurface.entity;
10975         int i, j, k, l, flagsmask;
10976         const msurface_t *surface;
10977         dp_model_t *model = ent->model;
10978         vec3_t v;
10979
10980         switch(vid.renderpath)
10981         {
10982         case RENDERPATH_GL11:
10983         case RENDERPATH_GL13:
10984         case RENDERPATH_GL20:
10985                 break;
10986         case RENDERPATH_D3D9:
10987                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10988                 return;
10989         case RENDERPATH_D3D10:
10990                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10991                 return;
10992         case RENDERPATH_D3D11:
10993                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10994                 return;
10995         case RENDERPATH_SOFT:
10996                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10997                 return;
10998         case RENDERPATH_GLES2:
10999                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11000                 return;
11001         }
11002
11003         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11004
11005 //      R_Mesh_ResetTextureState();
11006         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11007         GL_DepthRange(0, 1);
11008         GL_DepthTest(!r_showdisabledepthtest.integer);
11009         GL_DepthMask(false);
11010         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11011
11012         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11013         {
11014                 int triangleindex;
11015                 int bihleafindex;
11016                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11017                 const q3mbrush_t *brush;
11018                 const bih_t *bih = &model->collision_bih;
11019                 const bih_leaf_t *bihleaf;
11020                 float vertex3f[3][3];
11021                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11022                 cullbox = false;
11023                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11024                 {
11025                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11026                                 continue;
11027                         switch (bihleaf->type)
11028                         {
11029                         case BIH_BRUSH:
11030                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11031                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11032                                 {
11033                                         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);
11034                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11035                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11036                                 }
11037                                 break;
11038                         case BIH_COLLISIONTRIANGLE:
11039                                 triangleindex = bihleaf->itemindex;
11040                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11041                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11042                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11043                                 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);
11044                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11045                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11046                                 break;
11047                         case BIH_RENDERTRIANGLE:
11048                                 triangleindex = bihleaf->itemindex;
11049                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11050                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11051                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11052                                 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);
11053                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11054                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11055                                 break;
11056                         }
11057                 }
11058         }
11059
11060         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11061
11062         if (r_showtris.integer || (r_shownormals.value != 0))
11063         {
11064                 if (r_showdisabledepthtest.integer)
11065                 {
11066                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11067                         GL_DepthMask(false);
11068                 }
11069                 else
11070                 {
11071                         GL_BlendFunc(GL_ONE, GL_ZERO);
11072                         GL_DepthMask(true);
11073                 }
11074                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11075                 {
11076                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11077                                 continue;
11078                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11079                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11080                         {
11081                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11082                                 if (r_showtris.value > 0)
11083                                 {
11084                                         if (!rsurface.texture->currentlayers->depthmask)
11085                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11086                                         else if (ent == r_refdef.scene.worldentity)
11087                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11088                                         else
11089                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11090                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11091                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11092                                         RSurf_DrawBatch();
11093                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11094                                         CHECKGLERROR
11095                                 }
11096                                 if (r_shownormals.value < 0)
11097                                 {
11098                                         qglBegin(GL_LINES);
11099                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11100                                         {
11101                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11102                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11103                                                 qglVertex3f(v[0], v[1], v[2]);
11104                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11105                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11106                                                 qglVertex3f(v[0], v[1], v[2]);
11107                                         }
11108                                         qglEnd();
11109                                         CHECKGLERROR
11110                                 }
11111                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11112                                 {
11113                                         qglBegin(GL_LINES);
11114                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11115                                         {
11116                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11117                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11118                                                 qglVertex3f(v[0], v[1], v[2]);
11119                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11120                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11121                                                 qglVertex3f(v[0], v[1], v[2]);
11122                                         }
11123                                         qglEnd();
11124                                         CHECKGLERROR
11125                                         qglBegin(GL_LINES);
11126                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11127                                         {
11128                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11129                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11130                                                 qglVertex3f(v[0], v[1], v[2]);
11131                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11132                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11133                                                 qglVertex3f(v[0], v[1], v[2]);
11134                                         }
11135                                         qglEnd();
11136                                         CHECKGLERROR
11137                                         qglBegin(GL_LINES);
11138                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11139                                         {
11140                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11141                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11142                                                 qglVertex3f(v[0], v[1], v[2]);
11143                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11144                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11145                                                 qglVertex3f(v[0], v[1], v[2]);
11146                                         }
11147                                         qglEnd();
11148                                         CHECKGLERROR
11149                                 }
11150                         }
11151                 }
11152                 rsurface.texture = NULL;
11153         }
11154 }
11155
11156 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11157 int r_maxsurfacelist = 0;
11158 const msurface_t **r_surfacelist = NULL;
11159 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11160 {
11161         int i, j, endj, flagsmask;
11162         dp_model_t *model = r_refdef.scene.worldmodel;
11163         msurface_t *surfaces;
11164         unsigned char *update;
11165         int numsurfacelist = 0;
11166         if (model == NULL)
11167                 return;
11168
11169         if (r_maxsurfacelist < model->num_surfaces)
11170         {
11171                 r_maxsurfacelist = model->num_surfaces;
11172                 if (r_surfacelist)
11173                         Mem_Free((msurface_t**)r_surfacelist);
11174                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11175         }
11176
11177         RSurf_ActiveWorldEntity();
11178
11179         surfaces = model->data_surfaces;
11180         update = model->brushq1.lightmapupdateflags;
11181
11182         // update light styles on this submodel
11183         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11184         {
11185                 model_brush_lightstyleinfo_t *style;
11186                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11187                 {
11188                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11189                         {
11190                                 int *list = style->surfacelist;
11191                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11192                                 for (j = 0;j < style->numsurfaces;j++)
11193                                         update[list[j]] = true;
11194                         }
11195                 }
11196         }
11197
11198         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11199
11200         if (debug)
11201         {
11202                 R_DrawDebugModel();
11203                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11204                 return;
11205         }
11206
11207         rsurface.lightmaptexture = NULL;
11208         rsurface.deluxemaptexture = NULL;
11209         rsurface.uselightmaptexture = false;
11210         rsurface.texture = NULL;
11211         rsurface.rtlight = NULL;
11212         numsurfacelist = 0;
11213         // add visible surfaces to draw list
11214         for (i = 0;i < model->nummodelsurfaces;i++)
11215         {
11216                 j = model->sortedmodelsurfaces[i];
11217                 if (r_refdef.viewcache.world_surfacevisible[j])
11218                         r_surfacelist[numsurfacelist++] = surfaces + j;
11219         }
11220         // update lightmaps if needed
11221         if (model->brushq1.firstrender)
11222         {
11223                 model->brushq1.firstrender = false;
11224                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11225                         if (update[j])
11226                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11227         }
11228         else if (update)
11229         {
11230                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11231                         if (r_refdef.viewcache.world_surfacevisible[j])
11232                                 if (update[j])
11233                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11234         }
11235         // don't do anything if there were no surfaces
11236         if (!numsurfacelist)
11237         {
11238                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11239                 return;
11240         }
11241         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11242
11243         // add to stats if desired
11244         if (r_speeds.integer && !skysurfaces && !depthonly)
11245         {
11246                 r_refdef.stats.world_surfaces += numsurfacelist;
11247                 for (j = 0;j < numsurfacelist;j++)
11248                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11249         }
11250
11251         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11252 }
11253
11254 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11255 {
11256         int i, j, endj, flagsmask;
11257         dp_model_t *model = ent->model;
11258         msurface_t *surfaces;
11259         unsigned char *update;
11260         int numsurfacelist = 0;
11261         if (model == NULL)
11262                 return;
11263
11264         if (r_maxsurfacelist < model->num_surfaces)
11265         {
11266                 r_maxsurfacelist = model->num_surfaces;
11267                 if (r_surfacelist)
11268                         Mem_Free((msurface_t **)r_surfacelist);
11269                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11270         }
11271
11272         // if the model is static it doesn't matter what value we give for
11273         // wantnormals and wanttangents, so this logic uses only rules applicable
11274         // to a model, knowing that they are meaningless otherwise
11275         if (ent == r_refdef.scene.worldentity)
11276                 RSurf_ActiveWorldEntity();
11277         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11278                 RSurf_ActiveModelEntity(ent, false, false, false);
11279         else if (prepass)
11280                 RSurf_ActiveModelEntity(ent, true, true, true);
11281         else if (depthonly)
11282         {
11283                 switch (vid.renderpath)
11284                 {
11285                 case RENDERPATH_GL20:
11286                 case RENDERPATH_D3D9:
11287                 case RENDERPATH_D3D10:
11288                 case RENDERPATH_D3D11:
11289                 case RENDERPATH_SOFT:
11290                 case RENDERPATH_GLES2:
11291                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11292                         break;
11293                 case RENDERPATH_GL13:
11294                 case RENDERPATH_GL11:
11295                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11296                         break;
11297                 }
11298         }
11299         else
11300         {
11301                 switch (vid.renderpath)
11302                 {
11303                 case RENDERPATH_GL20:
11304                 case RENDERPATH_D3D9:
11305                 case RENDERPATH_D3D10:
11306                 case RENDERPATH_D3D11:
11307                 case RENDERPATH_SOFT:
11308                 case RENDERPATH_GLES2:
11309                         RSurf_ActiveModelEntity(ent, true, true, false);
11310                         break;
11311                 case RENDERPATH_GL13:
11312                 case RENDERPATH_GL11:
11313                         RSurf_ActiveModelEntity(ent, true, false, false);
11314                         break;
11315                 }
11316         }
11317
11318         surfaces = model->data_surfaces;
11319         update = model->brushq1.lightmapupdateflags;
11320
11321         // update light styles
11322         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11323         {
11324                 model_brush_lightstyleinfo_t *style;
11325                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11326                 {
11327                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11328                         {
11329                                 int *list = style->surfacelist;
11330                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11331                                 for (j = 0;j < style->numsurfaces;j++)
11332                                         update[list[j]] = true;
11333                         }
11334                 }
11335         }
11336
11337         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11338
11339         if (debug)
11340         {
11341                 R_DrawDebugModel();
11342                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11343                 return;
11344         }
11345
11346         rsurface.lightmaptexture = NULL;
11347         rsurface.deluxemaptexture = NULL;
11348         rsurface.uselightmaptexture = false;
11349         rsurface.texture = NULL;
11350         rsurface.rtlight = NULL;
11351         numsurfacelist = 0;
11352         // add visible surfaces to draw list
11353         for (i = 0;i < model->nummodelsurfaces;i++)
11354                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11355         // don't do anything if there were no surfaces
11356         if (!numsurfacelist)
11357         {
11358                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11359                 return;
11360         }
11361         // update lightmaps if needed
11362         if (update)
11363         {
11364                 int updated = 0;
11365                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11366                 {
11367                         if (update[j])
11368                         {
11369                                 updated++;
11370                                 R_BuildLightMap(ent, surfaces + j);
11371                         }
11372                 }
11373         }
11374         if (update)
11375                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11376                         if (update[j])
11377                                 R_BuildLightMap(ent, surfaces + j);
11378         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11379
11380         // add to stats if desired
11381         if (r_speeds.integer && !skysurfaces && !depthonly)
11382         {
11383                 r_refdef.stats.entities_surfaces += numsurfacelist;
11384                 for (j = 0;j < numsurfacelist;j++)
11385                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11386         }
11387
11388         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11389 }
11390
11391 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11392 {
11393         static texture_t texture;
11394         static msurface_t surface;
11395         const msurface_t *surfacelist = &surface;
11396
11397         // fake enough texture and surface state to render this geometry
11398
11399         texture.update_lastrenderframe = -1; // regenerate this texture
11400         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11401         texture.currentskinframe = skinframe;
11402         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11403         texture.offsetmapping = OFFSETMAPPING_OFF;
11404         texture.offsetscale = 1;
11405         texture.specularscalemod = 1;
11406         texture.specularpowermod = 1;
11407
11408         surface.texture = &texture;
11409         surface.num_triangles = numtriangles;
11410         surface.num_firsttriangle = firsttriangle;
11411         surface.num_vertices = numvertices;
11412         surface.num_firstvertex = firstvertex;
11413
11414         // now render it
11415         rsurface.texture = R_GetCurrentTexture(surface.texture);
11416         rsurface.lightmaptexture = NULL;
11417         rsurface.deluxemaptexture = NULL;
11418         rsurface.uselightmaptexture = false;
11419         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11420 }
11421
11422 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)
11423 {
11424         static msurface_t surface;
11425         const msurface_t *surfacelist = &surface;
11426
11427         // fake enough texture and surface state to render this geometry
11428         surface.texture = texture;
11429         surface.num_triangles = numtriangles;
11430         surface.num_firsttriangle = firsttriangle;
11431         surface.num_vertices = numvertices;
11432         surface.num_firstvertex = firstvertex;
11433
11434         // now render it
11435         rsurface.texture = R_GetCurrentTexture(surface.texture);
11436         rsurface.lightmaptexture = NULL;
11437         rsurface.deluxemaptexture = NULL;
11438         rsurface.uselightmaptexture = false;
11439         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11440 }