]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
disable VorteX's gamma corrected 2D drawing because it is broken with
[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", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 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"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 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)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 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"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 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)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 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"};
86 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"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 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"};
89 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"};
90 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"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 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)"};
99 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)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
103 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
104
105 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
106 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
107 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
108
109 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
110 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
111 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
112 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."};
113 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
114 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
115 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
116 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."};
117 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
118 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
119 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
120 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
121 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"};
122 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"};
123 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
124 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
126 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
127 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
128 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"};
129 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
130 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
131
132 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
133 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
134 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
135 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
136 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
137 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
138 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
139 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
140
141 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)"};
142 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"};
143
144 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
145 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
146 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
147
148 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"};
149 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"};
150 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
151 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
152 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"};
153 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)"};
154 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)"};
155 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
156
157 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)"};
158 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
159 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)"};
160 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
161 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)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
163 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
164 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173
174 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)"};
175 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
176 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"};
177 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
178 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
179 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
180 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
181
182 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
183 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
184 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
185 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
186
187 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
188 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
189 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
190 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
191 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
192 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
193 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
194
195 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
196 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
197 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
198 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)"};
199 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
200 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
201 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
202 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
204 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
205 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
206
207 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"};
208
209 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"};
210
211 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
212
213 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
214
215 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
216 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"};
217
218 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."};
219
220 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)"};
221
222 extern cvar_t v_glslgamma;
223
224 extern qboolean v_flipped_state;
225
226 static struct r_bloomstate_s
227 {
228         qboolean enabled;
229         qboolean hdr;
230
231         int bloomwidth, bloomheight;
232
233         textype_t texturetype;
234         int viewfbo; // used to check if r_viewfbo cvar has changed
235
236         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
237         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
238         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
239
240         int screentexturewidth, screentextureheight;
241         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
242
243         int bloomtexturewidth, bloomtextureheight;
244         rtexture_t *texture_bloom;
245
246         // arrays for rendering the screen passes
247         float screentexcoord2f[8];
248         float bloomtexcoord2f[8];
249         float offsettexcoord2f[8];
250
251         r_viewport_t viewport;
252 }
253 r_bloomstate;
254
255 r_waterstate_t r_waterstate;
256
257 /// shadow volume bsp struct with automatically growing nodes buffer
258 svbsp_t r_svbsp;
259
260 rtexture_t *r_texture_blanknormalmap;
261 rtexture_t *r_texture_white;
262 rtexture_t *r_texture_grey128;
263 rtexture_t *r_texture_black;
264 rtexture_t *r_texture_notexture;
265 rtexture_t *r_texture_whitecube;
266 rtexture_t *r_texture_normalizationcube;
267 rtexture_t *r_texture_fogattenuation;
268 rtexture_t *r_texture_fogheighttexture;
269 rtexture_t *r_texture_gammaramps;
270 unsigned int r_texture_gammaramps_serial;
271 //rtexture_t *r_texture_fogintensity;
272 rtexture_t *r_texture_reflectcube;
273
274 // TODO: hash lookups?
275 typedef struct cubemapinfo_s
276 {
277         char basename[64];
278         rtexture_t *texture;
279 }
280 cubemapinfo_t;
281
282 int r_texture_numcubemaps;
283 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
284
285 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
286 unsigned int r_numqueries;
287 unsigned int r_maxqueries;
288
289 typedef struct r_qwskincache_s
290 {
291         char name[MAX_QPATH];
292         skinframe_t *skinframe;
293 }
294 r_qwskincache_t;
295
296 static r_qwskincache_t *r_qwskincache;
297 static int r_qwskincache_size;
298
299 /// vertex coordinates for a quad that covers the screen exactly
300 extern const float r_screenvertex3f[12];
301 extern const float r_d3dscreenvertex3f[12];
302 const float r_screenvertex3f[12] =
303 {
304         0, 0, 0,
305         1, 0, 0,
306         1, 1, 0,
307         0, 1, 0
308 };
309 const float r_d3dscreenvertex3f[12] =
310 {
311         0, 1, 0,
312         1, 1, 0,
313         1, 0, 0,
314         0, 0, 0
315 };
316
317 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
318 {
319         int i;
320         for (i = 0;i < verts;i++)
321         {
322                 out[0] = in[0] * r;
323                 out[1] = in[1] * g;
324                 out[2] = in[2] * b;
325                 out[3] = in[3];
326                 in += 4;
327                 out += 4;
328         }
329 }
330
331 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
332 {
333         int i;
334         for (i = 0;i < verts;i++)
335         {
336                 out[0] = r;
337                 out[1] = g;
338                 out[2] = b;
339                 out[3] = a;
340                 out += 4;
341         }
342 }
343
344 // FIXME: move this to client?
345 void FOG_clear(void)
346 {
347         if (gamemode == GAME_NEHAHRA)
348         {
349                 Cvar_Set("gl_fogenable", "0");
350                 Cvar_Set("gl_fogdensity", "0.2");
351                 Cvar_Set("gl_fogred", "0.3");
352                 Cvar_Set("gl_foggreen", "0.3");
353                 Cvar_Set("gl_fogblue", "0.3");
354         }
355         r_refdef.fog_density = 0;
356         r_refdef.fog_red = 0;
357         r_refdef.fog_green = 0;
358         r_refdef.fog_blue = 0;
359         r_refdef.fog_alpha = 1;
360         r_refdef.fog_start = 0;
361         r_refdef.fog_end = 16384;
362         r_refdef.fog_height = 1<<30;
363         r_refdef.fog_fadedepth = 128;
364         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
365 }
366
367 static void R_BuildBlankTextures(void)
368 {
369         unsigned char data[4];
370         data[2] = 128; // normal X
371         data[1] = 128; // normal Y
372         data[0] = 255; // normal Z
373         data[3] = 128; // height
374         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 255;
376         data[1] = 255;
377         data[2] = 255;
378         data[3] = 255;
379         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 128;
381         data[1] = 128;
382         data[2] = 128;
383         data[3] = 255;
384         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 0;
386         data[1] = 0;
387         data[2] = 0;
388         data[3] = 255;
389         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 }
391
392 static void R_BuildNoTexture(void)
393 {
394         int x, y;
395         unsigned char pix[16][16][4];
396         // this makes a light grey/dark grey checkerboard texture
397         for (y = 0;y < 16;y++)
398         {
399                 for (x = 0;x < 16;x++)
400                 {
401                         if ((y < 8) ^ (x < 8))
402                         {
403                                 pix[y][x][0] = 128;
404                                 pix[y][x][1] = 128;
405                                 pix[y][x][2] = 128;
406                                 pix[y][x][3] = 255;
407                         }
408                         else
409                         {
410                                 pix[y][x][0] = 64;
411                                 pix[y][x][1] = 64;
412                                 pix[y][x][2] = 64;
413                                 pix[y][x][3] = 255;
414                         }
415                 }
416         }
417         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
418 }
419
420 static void R_BuildWhiteCube(void)
421 {
422         unsigned char data[6*1*1*4];
423         memset(data, 255, sizeof(data));
424         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
425 }
426
427 static void R_BuildNormalizationCube(void)
428 {
429         int x, y, side;
430         vec3_t v;
431         vec_t s, t, intensity;
432 #define NORMSIZE 64
433         unsigned char *data;
434         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
435         for (side = 0;side < 6;side++)
436         {
437                 for (y = 0;y < NORMSIZE;y++)
438                 {
439                         for (x = 0;x < NORMSIZE;x++)
440                         {
441                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
442                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 switch(side)
444                                 {
445                                 default:
446                                 case 0:
447                                         v[0] = 1;
448                                         v[1] = -t;
449                                         v[2] = -s;
450                                         break;
451                                 case 1:
452                                         v[0] = -1;
453                                         v[1] = -t;
454                                         v[2] = s;
455                                         break;
456                                 case 2:
457                                         v[0] = s;
458                                         v[1] = 1;
459                                         v[2] = t;
460                                         break;
461                                 case 3:
462                                         v[0] = s;
463                                         v[1] = -1;
464                                         v[2] = -t;
465                                         break;
466                                 case 4:
467                                         v[0] = s;
468                                         v[1] = -t;
469                                         v[2] = 1;
470                                         break;
471                                 case 5:
472                                         v[0] = -s;
473                                         v[1] = -t;
474                                         v[2] = -1;
475                                         break;
476                                 }
477                                 intensity = 127.0f / sqrt(DotProduct(v, v));
478                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
479                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
480                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
481                                 data[((side*64+y)*64+x)*4+3] = 255;
482                         }
483                 }
484         }
485         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
486         Mem_Free(data);
487 }
488
489 static void R_BuildFogTexture(void)
490 {
491         int x, b;
492 #define FOGWIDTH 256
493         unsigned char data1[FOGWIDTH][4];
494         //unsigned char data2[FOGWIDTH][4];
495         double d, r, alpha;
496
497         r_refdef.fogmasktable_start = r_refdef.fog_start;
498         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
499         r_refdef.fogmasktable_range = r_refdef.fogrange;
500         r_refdef.fogmasktable_density = r_refdef.fog_density;
501
502         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
503         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
504         {
505                 d = (x * r - r_refdef.fogmasktable_start);
506                 if(developer_extra.integer)
507                         Con_DPrintf("%f ", d);
508                 d = max(0, d);
509                 if (r_fog_exp2.integer)
510                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
511                 else
512                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
513                 if(developer_extra.integer)
514                         Con_DPrintf(" : %f ", alpha);
515                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
516                 if(developer_extra.integer)
517                         Con_DPrintf(" = %f\n", alpha);
518                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
519         }
520
521         for (x = 0;x < FOGWIDTH;x++)
522         {
523                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
524                 data1[x][0] = b;
525                 data1[x][1] = b;
526                 data1[x][2] = b;
527                 data1[x][3] = 255;
528                 //data2[x][0] = 255 - b;
529                 //data2[x][1] = 255 - b;
530                 //data2[x][2] = 255 - b;
531                 //data2[x][3] = 255;
532         }
533         if (r_texture_fogattenuation)
534         {
535                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
536                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537         }
538         else
539         {
540                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
541                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
542         }
543 }
544
545 static void R_BuildFogHeightTexture(void)
546 {
547         unsigned char *inpixels;
548         int size;
549         int x;
550         int y;
551         int j;
552         float c[4];
553         float f;
554         inpixels = NULL;
555         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
556         if (r_refdef.fogheighttexturename[0])
557                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
558         if (!inpixels)
559         {
560                 r_refdef.fog_height_tablesize = 0;
561                 if (r_texture_fogheighttexture)
562                         R_FreeTexture(r_texture_fogheighttexture);
563                 r_texture_fogheighttexture = NULL;
564                 if (r_refdef.fog_height_table2d)
565                         Mem_Free(r_refdef.fog_height_table2d);
566                 r_refdef.fog_height_table2d = NULL;
567                 if (r_refdef.fog_height_table1d)
568                         Mem_Free(r_refdef.fog_height_table1d);
569                 r_refdef.fog_height_table1d = NULL;
570                 return;
571         }
572         size = image_width;
573         r_refdef.fog_height_tablesize = size;
574         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
575         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
576         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
577         Mem_Free(inpixels);
578         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
579         // average fog color table accounting for every fog layer between a point
580         // and the camera.  (Note: attenuation is handled separately!)
581         for (y = 0;y < size;y++)
582         {
583                 for (x = 0;x < size;x++)
584                 {
585                         Vector4Clear(c);
586                         f = 0;
587                         if (x < y)
588                         {
589                                 for (j = x;j <= y;j++)
590                                 {
591                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592                                         f++;
593                                 }
594                         }
595                         else
596                         {
597                                 for (j = x;j >= y;j--)
598                                 {
599                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
600                                         f++;
601                                 }
602                         }
603                         f = 1.0f / f;
604                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
605                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
608                 }
609         }
610         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
611 }
612
613 //=======================================================================================================================================================
614
615 static const char *builtinshaderstring =
616 #include "shader_glsl.h"
617 ;
618
619 const char *builtinhlslshaderstring =
620 #include "shader_hlsl.h"
621 ;
622
623 char *glslshaderstring = NULL;
624 char *hlslshaderstring = NULL;
625
626 //=======================================================================================================================================================
627
628 typedef struct shaderpermutationinfo_s
629 {
630         const char *pretext;
631         const char *name;
632 }
633 shaderpermutationinfo_t;
634
635 typedef struct shadermodeinfo_s
636 {
637         const char *vertexfilename;
638         const char *geometryfilename;
639         const char *fragmentfilename;
640         const char *pretext;
641         const char *name;
642 }
643 shadermodeinfo_t;
644
645 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
646 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
647 {
648         {"#define USEDIFFUSE\n", " diffuse"},
649         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
650         {"#define USEVIEWTINT\n", " viewtint"},
651         {"#define USECOLORMAPPING\n", " colormapping"},
652         {"#define USESATURATION\n", " saturation"},
653         {"#define USEFOGINSIDE\n", " foginside"},
654         {"#define USEFOGOUTSIDE\n", " fogoutside"},
655         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
656         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
657         {"#define USEGAMMARAMPS\n", " gammaramps"},
658         {"#define USECUBEFILTER\n", " cubefilter"},
659         {"#define USEGLOW\n", " glow"},
660         {"#define USEBLOOM\n", " bloom"},
661         {"#define USESPECULAR\n", " specular"},
662         {"#define USEPOSTPROCESSING\n", " postprocessing"},
663         {"#define USEREFLECTION\n", " reflection"},
664         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
665         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
666         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
667         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
668         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
669         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
670         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
671         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673         {"#define USEALPHAKILL\n", " alphakill"},
674         {"#define USEREFLECTCUBE\n", " reflectcube"},
675         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676         {"#define USEBOUNCEGRID\n", " bouncegrid"},
677         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
678         {"#define USETRIPPY\n", " trippy"},
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_GL11:
1853         case RENDERPATH_GL13:
1854         case RENDERPATH_GLES1:
1855                 break;
1856         case RENDERPATH_SOFT:
1857                 break;
1858         }
1859 }
1860
1861 void R_GLSL_DumpShader_f(void)
1862 {
1863         int i;
1864         qfile_t *file;
1865
1866         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1867         if (file)
1868         {
1869                 FS_Print(file, "/* The engine may define the following macros:\n");
1870                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871                 for (i = 0;i < SHADERMODE_COUNT;i++)
1872                         FS_Print(file, glslshadermodeinfo[i].pretext);
1873                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874                         FS_Print(file, shaderpermutationinfo[i].pretext);
1875                 FS_Print(file, "*/\n");
1876                 FS_Print(file, builtinshaderstring);
1877                 FS_Close(file);
1878                 Con_Printf("glsl/default.glsl written\n");
1879         }
1880         else
1881                 Con_Printf("failed to write to glsl/default.glsl\n");
1882
1883         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1884         if (file)
1885         {
1886                 FS_Print(file, "/* The engine may define the following macros:\n");
1887                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888                 for (i = 0;i < SHADERMODE_COUNT;i++)
1889                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1890                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891                         FS_Print(file, shaderpermutationinfo[i].pretext);
1892                 FS_Print(file, "*/\n");
1893                 FS_Print(file, builtinhlslshaderstring);
1894                 FS_Close(file);
1895                 Con_Printf("hlsl/default.hlsl written\n");
1896         }
1897         else
1898                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1899 }
1900
1901 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1902 {
1903         unsigned int permutation = 0;
1904         if (r_trippy.integer && !notrippy)
1905                 permutation |= SHADERPERMUTATION_TRIPPY;
1906         permutation |= SHADERPERMUTATION_VIEWTINT;
1907         if (first)
1908                 permutation |= SHADERPERMUTATION_DIFFUSE;
1909         if (second)
1910                 permutation |= SHADERPERMUTATION_SPECULAR;
1911         if (texturemode == GL_MODULATE)
1912                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1913 // LordHavoc: VorteX broke the game by doing this, and did not cvar it properly, and did not add the proper checks (r_texture_sRGB_2d.integer would need to be checked), and it breaks with vid_sRGB where the gamma ramps are altered...
1914 //      if (usegamma && r_texture_gammaramps && v_glslgamma.integer && !vid_gammatables_trivial)
1915 //              permutation |= SHADERPERMUTATION_GAMMARAMPS;
1916         else if (texturemode == GL_ADD)
1917                 permutation |= SHADERPERMUTATION_GLOW;
1918         else if (texturemode == GL_DECAL)
1919                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1920         if (!second)
1921                 texturemode = GL_MODULATE;
1922         if (vid.allowalphatocoverage)
1923                 GL_AlphaToCoverage(false);
1924         switch (vid.renderpath)
1925         {
1926         case RENDERPATH_D3D9:
1927 #ifdef SUPPORTD3D
1928                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1929                 R_Mesh_TexBind(GL20TU_FIRST , first );
1930                 R_Mesh_TexBind(GL20TU_SECOND, second);
1931                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1932                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1933 #endif
1934                 break;
1935         case RENDERPATH_D3D10:
1936                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1937                 break;
1938         case RENDERPATH_D3D11:
1939                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1940                 break;
1941         case RENDERPATH_GL20:
1942         case RENDERPATH_GLES2:
1943                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1944                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1945                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1946                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1947                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1948                 break;
1949         case RENDERPATH_GL13:
1950         case RENDERPATH_GLES1:
1951                 R_Mesh_TexBind(0, first );
1952                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1953                 R_Mesh_TexBind(1, second);
1954                 if (second)
1955                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1956                 break;
1957         case RENDERPATH_GL11:
1958                 R_Mesh_TexBind(0, first );
1959                 break;
1960         case RENDERPATH_SOFT:
1961                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1962                 R_Mesh_TexBind(GL20TU_FIRST , first );
1963                 R_Mesh_TexBind(GL20TU_SECOND, second);
1964                 break;
1965         }
1966 }
1967
1968 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1969 {
1970         unsigned int permutation = 0;
1971         if (r_trippy.integer && !notrippy)
1972                 permutation |= SHADERPERMUTATION_TRIPPY;
1973         if (vid.allowalphatocoverage)
1974                 GL_AlphaToCoverage(false);
1975         switch (vid.renderpath)
1976         {
1977         case RENDERPATH_D3D9:
1978 #ifdef SUPPORTD3D
1979                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1980 #endif
1981                 break;
1982         case RENDERPATH_D3D10:
1983                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1984                 break;
1985         case RENDERPATH_D3D11:
1986                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1987                 break;
1988         case RENDERPATH_GL20:
1989         case RENDERPATH_GLES2:
1990                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1991                 break;
1992         case RENDERPATH_GL13:
1993         case RENDERPATH_GLES1:
1994                 R_Mesh_TexBind(0, 0);
1995                 R_Mesh_TexBind(1, 0);
1996                 break;
1997         case RENDERPATH_GL11:
1998                 R_Mesh_TexBind(0, 0);
1999                 break;
2000         case RENDERPATH_SOFT:
2001                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2002                 break;
2003         }
2004 }
2005
2006 void R_SetupShader_ShowDepth(qboolean notrippy)
2007 {
2008         int permutation = 0;
2009         if (r_trippy.integer && !notrippy)
2010                 permutation |= SHADERPERMUTATION_TRIPPY;
2011         if (vid.allowalphatocoverage)
2012                 GL_AlphaToCoverage(false);
2013         switch (vid.renderpath)
2014         {
2015         case RENDERPATH_D3D9:
2016 #ifdef SUPPORTHLSL
2017                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2018 #endif
2019                 break;
2020         case RENDERPATH_D3D10:
2021                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2022                 break;
2023         case RENDERPATH_D3D11:
2024                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2025                 break;
2026         case RENDERPATH_GL20:
2027         case RENDERPATH_GLES2:
2028                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2029                 break;
2030         case RENDERPATH_GL13:
2031         case RENDERPATH_GLES1:
2032                 break;
2033         case RENDERPATH_GL11:
2034                 break;
2035         case RENDERPATH_SOFT:
2036                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2037                 break;
2038         }
2039 }
2040
2041 extern qboolean r_shadow_usingdeferredprepass;
2042 extern cvar_t r_shadow_deferred_8bitrange;
2043 extern rtexture_t *r_shadow_attenuationgradienttexture;
2044 extern rtexture_t *r_shadow_attenuation2dtexture;
2045 extern rtexture_t *r_shadow_attenuation3dtexture;
2046 extern qboolean r_shadow_usingshadowmap2d;
2047 extern qboolean r_shadow_usingshadowmaportho;
2048 extern float r_shadow_shadowmap_texturescale[2];
2049 extern float r_shadow_shadowmap_parameters[4];
2050 extern qboolean r_shadow_shadowmapvsdct;
2051 extern qboolean r_shadow_shadowmapsampler;
2052 extern int r_shadow_shadowmappcf;
2053 extern rtexture_t *r_shadow_shadowmap2dtexture;
2054 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2055 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2056 extern matrix4x4_t r_shadow_shadowmapmatrix;
2057 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2058 extern int r_shadow_prepass_width;
2059 extern int r_shadow_prepass_height;
2060 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2061 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2062 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2063 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2064 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2065
2066 #define BLENDFUNC_ALLOWS_COLORMOD      1
2067 #define BLENDFUNC_ALLOWS_FOG           2
2068 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2069 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2070 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2071 static int R_BlendFuncFlags(int src, int dst)
2072 {
2073         int r = 0;
2074
2075         // a blendfunc allows colormod if:
2076         // a) it can never keep the destination pixel invariant, or
2077         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2078         // this is to prevent unintended side effects from colormod
2079
2080         // a blendfunc allows fog if:
2081         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2082         // this is to prevent unintended side effects from fog
2083
2084         // these checks are the output of fogeval.pl
2085
2086         r |= BLENDFUNC_ALLOWS_COLORMOD;
2087         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2088         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2091         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2092         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2093         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2095         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2096         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2100         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2101         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2107         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108
2109         return r;
2110 }
2111
2112 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, qboolean notrippy)
2113 {
2114         // select a permutation of the lighting shader appropriate to this
2115         // combination of texture, entity, light source, and fogging, only use the
2116         // minimum features necessary to avoid wasting rendering time in the
2117         // fragment shader on features that are not being used
2118         unsigned int permutation = 0;
2119         unsigned int mode = 0;
2120         int blendfuncflags;
2121         static float dummy_colormod[3] = {1, 1, 1};
2122         float *colormod = rsurface.colormod;
2123         float m16f[16];
2124         matrix4x4_t tempmatrix;
2125         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2126         if (r_trippy.integer && !notrippy)
2127                 permutation |= SHADERPERMUTATION_TRIPPY;
2128         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2129                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2130         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2131                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2132         if (rsurfacepass == RSURFPASS_BACKGROUND)
2133         {
2134                 // distorted background
2135                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2136                 {
2137                         mode = SHADERMODE_WATER;
2138                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2139                         {
2140                                 // this is the right thing to do for wateralpha
2141                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2142                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2143                         }
2144                         else
2145                         {
2146                                 // this is the right thing to do for entity alpha
2147                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2148                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2149                         }
2150                 }
2151                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2152                 {
2153                         mode = SHADERMODE_REFRACTION;
2154                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2155                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2156                 }
2157                 else
2158                 {
2159                         mode = SHADERMODE_GENERIC;
2160                         permutation |= SHADERPERMUTATION_DIFFUSE;
2161                         GL_BlendFunc(GL_ONE, GL_ZERO);
2162                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2163                 }
2164                 if (vid.allowalphatocoverage)
2165                         GL_AlphaToCoverage(false);
2166         }
2167         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2168         {
2169                 if (r_glsl_offsetmapping.integer)
2170                 {
2171                         switch(rsurface.texture->offsetmapping)
2172                         {
2173                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2174                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2175                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2176                         case OFFSETMAPPING_OFF: break;
2177                         }
2178                 }
2179                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2180                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2181                 // normalmap (deferred prepass), may use alpha test on diffuse
2182                 mode = SHADERMODE_DEFERREDGEOMETRY;
2183                 GL_BlendFunc(GL_ONE, GL_ZERO);
2184                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2185                 if (vid.allowalphatocoverage)
2186                         GL_AlphaToCoverage(false);
2187         }
2188         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2189         {
2190                 if (r_glsl_offsetmapping.integer)
2191                 {
2192                         switch(rsurface.texture->offsetmapping)
2193                         {
2194                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2195                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2197                         case OFFSETMAPPING_OFF: break;
2198                         }
2199                 }
2200                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2201                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2202                 // light source
2203                 mode = SHADERMODE_LIGHTSOURCE;
2204                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2205                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2206                 if (diffusescale > 0)
2207                         permutation |= SHADERPERMUTATION_DIFFUSE;
2208                 if (specularscale > 0)
2209                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2210                 if (r_refdef.fogenabled)
2211                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2212                 if (rsurface.texture->colormapping)
2213                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2214                 if (r_shadow_usingshadowmap2d)
2215                 {
2216                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2217                         if(r_shadow_shadowmapvsdct)
2218                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2219
2220                         if (r_shadow_shadowmapsampler)
2221                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2222                         if (r_shadow_shadowmappcf > 1)
2223                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2224                         else if (r_shadow_shadowmappcf)
2225                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2226                 }
2227                 if (rsurface.texture->reflectmasktexture)
2228                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2229                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2230                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2231                 if (vid.allowalphatocoverage)
2232                         GL_AlphaToCoverage(false);
2233         }
2234         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2235         {
2236                 if (r_glsl_offsetmapping.integer)
2237                 {
2238                         switch(rsurface.texture->offsetmapping)
2239                         {
2240                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2241                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243                         case OFFSETMAPPING_OFF: break;
2244                         }
2245                 }
2246                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2247                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2248                 // unshaded geometry (fullbright or ambient model lighting)
2249                 mode = SHADERMODE_FLATCOLOR;
2250                 ambientscale = diffusescale = specularscale = 0;
2251                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2252                         permutation |= SHADERPERMUTATION_GLOW;
2253                 if (r_refdef.fogenabled)
2254                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2255                 if (rsurface.texture->colormapping)
2256                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2257                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2258                 {
2259                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2260                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2261
2262                         if (r_shadow_shadowmapsampler)
2263                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2264                         if (r_shadow_shadowmappcf > 1)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2266                         else if (r_shadow_shadowmappcf)
2267                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2268                 }
2269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2270                         permutation |= SHADERPERMUTATION_REFLECTION;
2271                 if (rsurface.texture->reflectmasktexture)
2272                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2273                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2274                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2275                 // when using alphatocoverage, we don't need alphakill
2276                 if (vid.allowalphatocoverage)
2277                 {
2278                         if (r_transparent_alphatocoverage.integer)
2279                         {
2280                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2281                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2282                         }
2283                         else
2284                                 GL_AlphaToCoverage(false);
2285                 }
2286         }
2287         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2288         {
2289                 if (r_glsl_offsetmapping.integer)
2290                 {
2291                         switch(rsurface.texture->offsetmapping)
2292                         {
2293                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2294                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296                         case OFFSETMAPPING_OFF: break;
2297                         }
2298                 }
2299                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2300                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2301                 // directional model lighting
2302                 mode = SHADERMODE_LIGHTDIRECTION;
2303                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2304                         permutation |= SHADERPERMUTATION_GLOW;
2305                 permutation |= SHADERPERMUTATION_DIFFUSE;
2306                 if (specularscale > 0)
2307                         permutation |= SHADERPERMUTATION_SPECULAR;
2308                 if (r_refdef.fogenabled)
2309                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2310                 if (rsurface.texture->colormapping)
2311                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2312                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2313                 {
2314                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2315                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2316
2317                         if (r_shadow_shadowmapsampler)
2318                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2319                         if (r_shadow_shadowmappcf > 1)
2320                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2321                         else if (r_shadow_shadowmappcf)
2322                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2323                 }
2324                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2325                         permutation |= SHADERPERMUTATION_REFLECTION;
2326                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2327                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2328                 if (rsurface.texture->reflectmasktexture)
2329                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2330                 if (r_shadow_bouncegridtexture)
2331                 {
2332                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2333                         if (r_shadow_bouncegriddirectional)
2334                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2335                 }
2336                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2337                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2338                 // when using alphatocoverage, we don't need alphakill
2339                 if (vid.allowalphatocoverage)
2340                 {
2341                         if (r_transparent_alphatocoverage.integer)
2342                         {
2343                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2344                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2345                         }
2346                         else
2347                                 GL_AlphaToCoverage(false);
2348                 }
2349         }
2350         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2351         {
2352                 if (r_glsl_offsetmapping.integer)
2353                 {
2354                         switch(rsurface.texture->offsetmapping)
2355                         {
2356                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2357                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2358                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2359                         case OFFSETMAPPING_OFF: break;
2360                         }
2361                 }
2362                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2363                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2364                 // ambient model lighting
2365                 mode = SHADERMODE_LIGHTDIRECTION;
2366                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2367                         permutation |= SHADERPERMUTATION_GLOW;
2368                 if (r_refdef.fogenabled)
2369                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2370                 if (rsurface.texture->colormapping)
2371                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2372                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2373                 {
2374                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2375                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2376
2377                         if (r_shadow_shadowmapsampler)
2378                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2379                         if (r_shadow_shadowmappcf > 1)
2380                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2381                         else if (r_shadow_shadowmappcf)
2382                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2383                 }
2384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2385                         permutation |= SHADERPERMUTATION_REFLECTION;
2386                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2387                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2388                 if (rsurface.texture->reflectmasktexture)
2389                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2390                 if (r_shadow_bouncegridtexture)
2391                 {
2392                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2393                         if (r_shadow_bouncegriddirectional)
2394                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2395                 }
2396                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2397                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2398                 // when using alphatocoverage, we don't need alphakill
2399                 if (vid.allowalphatocoverage)
2400                 {
2401                         if (r_transparent_alphatocoverage.integer)
2402                         {
2403                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2404                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2405                         }
2406                         else
2407                                 GL_AlphaToCoverage(false);
2408                 }
2409         }
2410         else
2411         {
2412                 if (r_glsl_offsetmapping.integer)
2413                 {
2414                         switch(rsurface.texture->offsetmapping)
2415                         {
2416                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2417                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2418                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2419                         case OFFSETMAPPING_OFF: break;
2420                         }
2421                 }
2422                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2423                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2424                 // lightmapped wall
2425                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2426                         permutation |= SHADERPERMUTATION_GLOW;
2427                 if (r_refdef.fogenabled)
2428                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2429                 if (rsurface.texture->colormapping)
2430                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2431                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2432                 {
2433                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2434                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2435
2436                         if (r_shadow_shadowmapsampler)
2437                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2438                         if (r_shadow_shadowmappcf > 1)
2439                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2440                         else if (r_shadow_shadowmappcf)
2441                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2442                 }
2443                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2444                         permutation |= SHADERPERMUTATION_REFLECTION;
2445                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2446                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2447                 if (rsurface.texture->reflectmasktexture)
2448                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2449                 if (FAKELIGHT_ENABLED)
2450                 {
2451                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2452                         mode = SHADERMODE_FAKELIGHT;
2453                         permutation |= SHADERPERMUTATION_DIFFUSE;
2454                         if (specularscale > 0)
2455                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2456                 }
2457                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2458                 {
2459                         // deluxemapping (light direction texture)
2460                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2462                         else
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2464                         permutation |= SHADERPERMUTATION_DIFFUSE;
2465                         if (specularscale > 0)
2466                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2467                 }
2468                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2469                 {
2470                         // fake deluxemapping (uniform light direction in tangentspace)
2471                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2472                         permutation |= SHADERPERMUTATION_DIFFUSE;
2473                         if (specularscale > 0)
2474                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2475                 }
2476                 else if (rsurface.uselightmaptexture)
2477                 {
2478                         // ordinary lightmapping (q1bsp, q3bsp)
2479                         mode = SHADERMODE_LIGHTMAP;
2480                 }
2481                 else
2482                 {
2483                         // ordinary vertex coloring (q3bsp)
2484                         mode = SHADERMODE_VERTEXCOLOR;
2485                 }
2486                 if (r_shadow_bouncegridtexture)
2487                 {
2488                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2489                         if (r_shadow_bouncegriddirectional)
2490                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2491                 }
2492                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2493                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494                 // when using alphatocoverage, we don't need alphakill
2495                 if (vid.allowalphatocoverage)
2496                 {
2497                         if (r_transparent_alphatocoverage.integer)
2498                         {
2499                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2500                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2501                         }
2502                         else
2503                                 GL_AlphaToCoverage(false);
2504                 }
2505         }
2506         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2507                 colormod = dummy_colormod;
2508         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2509                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2510         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2511                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2512         switch(vid.renderpath)
2513         {
2514         case RENDERPATH_D3D9:
2515 #ifdef SUPPORTD3D
2516                 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);
2517                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2518                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2519                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2520                 if (mode == SHADERMODE_LIGHTSOURCE)
2521                 {
2522                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2523                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2524                 }
2525                 else
2526                 {
2527                         if (mode == SHADERMODE_LIGHTDIRECTION)
2528                         {
2529                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2530                         }
2531                 }
2532                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2533                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2534                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2535                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2536                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2537
2538                 if (mode == SHADERMODE_LIGHTSOURCE)
2539                 {
2540                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2541                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2542                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2545
2546                         // additive passes are only darkened by fog, not tinted
2547                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2548                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2549                 }
2550                 else
2551                 {
2552                         if (mode == SHADERMODE_FLATCOLOR)
2553                         {
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2555                         }
2556                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2557                         {
2558                                 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]);
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2560                                 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);
2561                                 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);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2565                         }
2566                         else
2567                         {
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2570                                 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);
2571                                 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);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2573                         }
2574                         // additive passes are only darkened by fog, not tinted
2575                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2577                         else
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2579                         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);
2580                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2584                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2585                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2587                         if (mode == SHADERMODE_WATER)
2588                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2589                 }
2590                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2591                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2592                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2593                 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));
2594                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2595                 if (rsurface.texture->pantstexture)
2596                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2597                 else
2598                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2599                 if (rsurface.texture->shirttexture)
2600                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2601                 else
2602                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2603                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2604                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2605                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2607                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2608                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2609                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2610                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2611                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2612                         );
2613                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2614                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2615
2616                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2617                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2618                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2619                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2620                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2622                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2624                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2625                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2626                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2627                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2628                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2629                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2630                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2631                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2632                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2633                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2634                 {
2635                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2636                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2637                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2638                 }
2639                 else
2640                 {
2641                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2642                 }
2643 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2644 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2645                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2646                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2647                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2648                 {
2649                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2650                         if (rsurface.rtlight)
2651                         {
2652                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2653                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2654                         }
2655                 }
2656 #endif
2657                 break;
2658         case RENDERPATH_D3D10:
2659                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2660                 break;
2661         case RENDERPATH_D3D11:
2662                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2663                 break;
2664         case RENDERPATH_GL20:
2665         case RENDERPATH_GLES2:
2666                 if (!vid.useinterleavedarrays)
2667                 {
2668                         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);
2669                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2670                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2672                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2676                 }
2677                 else
2678                 {
2679                         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);
2680                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2681                 }
2682                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2683                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2684                 if (mode == SHADERMODE_LIGHTSOURCE)
2685                 {
2686                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2687                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2688                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2689                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2690                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2691                         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);
2692         
2693                         // additive passes are only darkened by fog, not tinted
2694                         if (r_glsl_permutation->loc_FogColor >= 0)
2695                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2696                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2697                 }
2698                 else
2699                 {
2700                         if (mode == SHADERMODE_FLATCOLOR)
2701                         {
2702                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2703                         }
2704                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2705                         {
2706                                 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]);
2707                                 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]);
2708                                 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);
2709                                 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);
2710                                 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);
2711                                 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]);
2712                                 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]);
2713                         }
2714                         else
2715                         {
2716                                 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]);
2717                                 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]);
2718                                 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);
2719                                 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);
2720                                 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);
2721                         }
2722                         // additive passes are only darkened by fog, not tinted
2723                         if (r_glsl_permutation->loc_FogColor >= 0)
2724                         {
2725                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2726                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2727                                 else
2728                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2729                         }
2730                         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);
2731                         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]);
2732                         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]);
2733                         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]);
2734                         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]);
2735                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2736                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2737                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2738                         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]);
2739                 }
2740                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2741                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2742                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2743                 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]);
2744                 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]);
2745
2746                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2747                 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));
2748                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2749                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2750                 {
2751                         if (rsurface.texture->pantstexture)
2752                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2753                         else
2754                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2755                 }
2756                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2757                 {
2758                         if (rsurface.texture->shirttexture)
2759                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2760                         else
2761                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2762                 }
2763                 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]);
2764                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2765                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2766                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2767                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2768                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2769                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2770                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2771                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2772                         );
2773                 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]);
2774                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2775                 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);}
2776                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2777
2778                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2779                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2780                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2781                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2782                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2783                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2784                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2785                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2786                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2787                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2788                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2789                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2790                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2791                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2792                 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);
2793                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2794                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2795                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2796                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2797                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2798                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2799                 {
2800                         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);
2801                         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);
2802                         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);
2803                 }
2804                 else
2805                 {
2806                         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);
2807                 }
2808                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2809                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2810                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2811                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2812                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2813                 {
2814                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2815                         if (rsurface.rtlight)
2816                         {
2817                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2818                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2819                         }
2820                 }
2821                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2822                 CHECKGLERROR
2823                 break;
2824         case RENDERPATH_GL11:
2825         case RENDERPATH_GL13:
2826         case RENDERPATH_GLES1:
2827                 break;
2828         case RENDERPATH_SOFT:
2829                 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);
2830                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2831                 R_SetupShader_SetPermutationSoft(mode, permutation);
2832                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2833                 if (mode == SHADERMODE_LIGHTSOURCE)
2834                 {
2835                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2836                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2837                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2838                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2839                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2840                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2841         
2842                         // additive passes are only darkened by fog, not tinted
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2844                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2845                 }
2846                 else
2847                 {
2848                         if (mode == SHADERMODE_FLATCOLOR)
2849                         {
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2851                         }
2852                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2853                         {
2854                                 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]);
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2856                                 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);
2857                                 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);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2859                                 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]);
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2861                         }
2862                         else
2863                         {
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2866                                 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);
2867                                 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);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2869                         }
2870                         // additive passes are only darkened by fog, not tinted
2871                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2873                         else
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2875                         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);
2876                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2877                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2878                         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]);
2879                         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]);
2880                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2881                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2882                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2883                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2884                 }
2885                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2886                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2887                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2888                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2889                 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]);
2890
2891                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2892                 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));
2893                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2894                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2895                 {
2896                         if (rsurface.texture->pantstexture)
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2898                         else
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2900                 }
2901                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2902                 {
2903                         if (rsurface.texture->shirttexture)
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2905                         else
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2907                 }
2908                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2909                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2910                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2911                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2912                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2913                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2914                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2915                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2916                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2917                         );
2918                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2919                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2920
2921                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2922                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2923                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2924                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2925                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2926                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2927                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2928                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2929                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2930                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2931                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2932                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2933                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2934                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2935                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2936                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2937                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2938                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2939                 {
2940                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2941                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2942                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2943                 }
2944                 else
2945                 {
2946                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2947                 }
2948 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2949 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2950                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2951                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2952                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2953                 {
2954                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2955                         if (rsurface.rtlight)
2956                         {
2957                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2958                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2959                         }
2960                 }
2961                 break;
2962         }
2963 }
2964
2965 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2966 {
2967         // select a permutation of the lighting shader appropriate to this
2968         // combination of texture, entity, light source, and fogging, only use the
2969         // minimum features necessary to avoid wasting rendering time in the
2970         // fragment shader on features that are not being used
2971         unsigned int permutation = 0;
2972         unsigned int mode = 0;
2973         const float *lightcolorbase = rtlight->currentcolor;
2974         float ambientscale = rtlight->ambientscale;
2975         float diffusescale = rtlight->diffusescale;
2976         float specularscale = rtlight->specularscale;
2977         // this is the location of the light in view space
2978         vec3_t viewlightorigin;
2979         // this transforms from view space (camera) to light space (cubemap)
2980         matrix4x4_t viewtolight;
2981         matrix4x4_t lighttoview;
2982         float viewtolight16f[16];
2983         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2984         // light source
2985         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2986         if (rtlight->currentcubemap != r_texture_whitecube)
2987                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2988         if (diffusescale > 0)
2989                 permutation |= SHADERPERMUTATION_DIFFUSE;
2990         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2991                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2992         if (r_shadow_usingshadowmap2d)
2993         {
2994                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2995                 if (r_shadow_shadowmapvsdct)
2996                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2997
2998                 if (r_shadow_shadowmapsampler)
2999                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3000                 if (r_shadow_shadowmappcf > 1)
3001                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3002                 else if (r_shadow_shadowmappcf)
3003                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3004         }
3005         if (vid.allowalphatocoverage)
3006                 GL_AlphaToCoverage(false);
3007         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3008         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3009         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3010         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3011         switch(vid.renderpath)
3012         {
3013         case RENDERPATH_D3D9:
3014 #ifdef SUPPORTD3D
3015                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3016                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3017                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3018                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3019                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3020                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3021                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3022                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3023                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3024                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3025                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3026
3027                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3028                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3029                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3030                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3031                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3032                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3033 #endif
3034                 break;
3035         case RENDERPATH_D3D10:
3036                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3037                 break;
3038         case RENDERPATH_D3D11:
3039                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3040                 break;
3041         case RENDERPATH_GL20:
3042         case RENDERPATH_GLES2:
3043                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3044                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3045                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3046                 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);
3047                 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);
3048                 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);
3049                 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]);
3050                 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]);
3051                 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));
3052                 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]);
3053                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3054
3055                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3056                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3057                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3058                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3059                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3060                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3061                 break;
3062         case RENDERPATH_GL11:
3063         case RENDERPATH_GL13:
3064         case RENDERPATH_GLES1:
3065                 break;
3066         case RENDERPATH_SOFT:
3067                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3068                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3069                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3070                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3071                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3072                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3073                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3074                 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]);
3075                 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));
3076                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3077                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3078
3079                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3080                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3081                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3082                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3083                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3084                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3085                 break;
3086         }
3087 }
3088
3089 #define SKINFRAME_HASH 1024
3090
3091 typedef struct
3092 {
3093         int loadsequence; // incremented each level change
3094         memexpandablearray_t array;
3095         skinframe_t *hash[SKINFRAME_HASH];
3096 }
3097 r_skinframe_t;
3098 r_skinframe_t r_skinframe;
3099
3100 void R_SkinFrame_PrepareForPurge(void)
3101 {
3102         r_skinframe.loadsequence++;
3103         // wrap it without hitting zero
3104         if (r_skinframe.loadsequence >= 200)
3105                 r_skinframe.loadsequence = 1;
3106 }
3107
3108 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3109 {
3110         if (!skinframe)
3111                 return;
3112         // mark the skinframe as used for the purging code
3113         skinframe->loadsequence = r_skinframe.loadsequence;
3114 }
3115
3116 void R_SkinFrame_Purge(void)
3117 {
3118         int i;
3119         skinframe_t *s;
3120         for (i = 0;i < SKINFRAME_HASH;i++)
3121         {
3122                 for (s = r_skinframe.hash[i];s;s = s->next)
3123                 {
3124                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3125                         {
3126                                 if (s->merged == s->base)
3127                                         s->merged = NULL;
3128                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3129                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3130                                 R_PurgeTexture(s->merged);s->merged = NULL;
3131                                 R_PurgeTexture(s->base  );s->base   = NULL;
3132                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3133                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3134                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3135                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3136                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3137                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3138                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3139                                 s->loadsequence = 0;
3140                         }
3141                 }
3142         }
3143 }
3144
3145 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3146         skinframe_t *item;
3147         char basename[MAX_QPATH];
3148
3149         Image_StripImageExtension(name, basename, sizeof(basename));
3150
3151         if( last == NULL ) {
3152                 int hashindex;
3153                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3154                 item = r_skinframe.hash[hashindex];
3155         } else {
3156                 item = last->next;
3157         }
3158
3159         // linearly search through the hash bucket
3160         for( ; item ; item = item->next ) {
3161                 if( !strcmp( item->basename, basename ) ) {
3162                         return item;
3163                 }
3164         }
3165         return NULL;
3166 }
3167
3168 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3169 {
3170         skinframe_t *item;
3171         int hashindex;
3172         char basename[MAX_QPATH];
3173
3174         Image_StripImageExtension(name, basename, sizeof(basename));
3175
3176         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3177         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3178                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3179                         break;
3180
3181         if (!item) {
3182                 rtexture_t *dyntexture;
3183                 // check whether its a dynamic texture
3184                 dyntexture = CL_GetDynTexture( basename );
3185                 if (!add && !dyntexture)
3186                         return NULL;
3187                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3188                 memset(item, 0, sizeof(*item));
3189                 strlcpy(item->basename, basename, sizeof(item->basename));
3190                 item->base = dyntexture; // either NULL or dyntexture handle
3191                 item->textureflags = textureflags;
3192                 item->comparewidth = comparewidth;
3193                 item->compareheight = compareheight;
3194                 item->comparecrc = comparecrc;
3195                 item->next = r_skinframe.hash[hashindex];
3196                 r_skinframe.hash[hashindex] = item;
3197         }
3198         else if( item->base == NULL )
3199         {
3200                 rtexture_t *dyntexture;
3201                 // check whether its a dynamic texture
3202                 // 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]
3203                 dyntexture = CL_GetDynTexture( basename );
3204                 item->base = dyntexture; // either NULL or dyntexture handle
3205         }
3206
3207         R_SkinFrame_MarkUsed(item);
3208         return item;
3209 }
3210
3211 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3212         { \
3213                 unsigned long long avgcolor[5], wsum; \
3214                 int pix, comp, w; \
3215                 avgcolor[0] = 0; \
3216                 avgcolor[1] = 0; \
3217                 avgcolor[2] = 0; \
3218                 avgcolor[3] = 0; \
3219                 avgcolor[4] = 0; \
3220                 wsum = 0; \
3221                 for(pix = 0; pix < cnt; ++pix) \
3222                 { \
3223                         w = 0; \
3224                         for(comp = 0; comp < 3; ++comp) \
3225                                 w += getpixel; \
3226                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3227                         { \
3228                                 ++wsum; \
3229                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3230                                 w = getpixel; \
3231                                 for(comp = 0; comp < 3; ++comp) \
3232                                         avgcolor[comp] += getpixel * w; \
3233                                 avgcolor[3] += w; \
3234                         } \
3235                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3236                         avgcolor[4] += getpixel; \
3237                 } \
3238                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3239                         avgcolor[3] = 1; \
3240                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3241                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3242                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3243                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3244         }
3245
3246 extern cvar_t gl_picmip;
3247 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3248 {
3249         int j;
3250         unsigned char *pixels;
3251         unsigned char *bumppixels;
3252         unsigned char *basepixels = NULL;
3253         int basepixels_width = 0;
3254         int basepixels_height = 0;
3255         skinframe_t *skinframe;
3256         rtexture_t *ddsbase = NULL;
3257         qboolean ddshasalpha = false;
3258         float ddsavgcolor[4];
3259         char basename[MAX_QPATH];
3260         int miplevel = R_PicmipForFlags(textureflags);
3261         int savemiplevel = miplevel;
3262         int mymiplevel;
3263
3264         if (cls.state == ca_dedicated)
3265                 return NULL;
3266
3267         // return an existing skinframe if already loaded
3268         // if loading of the first image fails, don't make a new skinframe as it
3269         // would cause all future lookups of this to be missing
3270         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3271         if (skinframe && skinframe->base)
3272                 return skinframe;
3273
3274         Image_StripImageExtension(name, basename, sizeof(basename));
3275
3276         // check for DDS texture file first
3277         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3278         {
3279                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3280                 if (basepixels == NULL)
3281                         return NULL;
3282         }
3283
3284         // FIXME handle miplevel
3285
3286         if (developer_loading.integer)
3287                 Con_Printf("loading skin \"%s\"\n", name);
3288
3289         // we've got some pixels to store, so really allocate this new texture now
3290         if (!skinframe)
3291                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3292         skinframe->stain = NULL;
3293         skinframe->merged = NULL;
3294         skinframe->base = NULL;
3295         skinframe->pants = NULL;
3296         skinframe->shirt = NULL;
3297         skinframe->nmap = NULL;
3298         skinframe->gloss = NULL;
3299         skinframe->glow = NULL;
3300         skinframe->fog = NULL;
3301         skinframe->reflect = NULL;
3302         skinframe->hasalpha = false;
3303
3304         if (ddsbase)
3305         {
3306                 skinframe->base = ddsbase;
3307                 skinframe->hasalpha = ddshasalpha;
3308                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3309                 if (r_loadfog && skinframe->hasalpha)
3310                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3311                 //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]);
3312         }
3313         else
3314         {
3315                 basepixels_width = image_width;
3316                 basepixels_height = image_height;
3317                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3318                 if (textureflags & TEXF_ALPHA)
3319                 {
3320                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3321                         {
3322                                 if (basepixels[j] < 255)
3323                                 {
3324                                         skinframe->hasalpha = true;
3325                                         break;
3326                                 }
3327                         }
3328                         if (r_loadfog && skinframe->hasalpha)
3329                         {
3330                                 // has transparent pixels
3331                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3332                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3333                                 {
3334                                         pixels[j+0] = 255;
3335                                         pixels[j+1] = 255;
3336                                         pixels[j+2] = 255;
3337                                         pixels[j+3] = basepixels[j+3];
3338                                 }
3339                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3340                                 Mem_Free(pixels);
3341                         }
3342                 }
3343                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3344                 //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]);
3345                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3346                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3347                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3348                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3349         }
3350
3351         if (r_loaddds)
3352         {
3353                 mymiplevel = savemiplevel;
3354                 if (r_loadnormalmap)
3355                         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);
3356                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3357                 if (r_loadgloss)
3358                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3359                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3360                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3361                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3362         }
3363
3364         // _norm is the name used by tenebrae and has been adopted as standard
3365         if (r_loadnormalmap && skinframe->nmap == NULL)
3366         {
3367                 mymiplevel = savemiplevel;
3368                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3369                 {
3370                         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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3371                         Mem_Free(pixels);
3372                         pixels = NULL;
3373                 }
3374                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3375                 {
3376                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3377                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3378                         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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3379                         Mem_Free(pixels);
3380                         Mem_Free(bumppixels);
3381                 }
3382                 else if (r_shadow_bumpscale_basetexture.value > 0)
3383                 {
3384                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3385                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3386                         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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3387                         Mem_Free(pixels);
3388                 }
3389                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3390                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3391         }
3392
3393         // _luma is supported only for tenebrae compatibility
3394         // _glow is the preferred name
3395         mymiplevel = savemiplevel;
3396         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3397         {
3398                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3399                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3400                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3401                 Mem_Free(pixels);pixels = NULL;
3402         }
3403
3404         mymiplevel = savemiplevel;
3405         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3406         {
3407                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3408                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3409                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3410                 Mem_Free(pixels);
3411                 pixels = NULL;
3412         }
3413
3414         mymiplevel = savemiplevel;
3415         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3416         {
3417                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3418                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3419                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3420                 Mem_Free(pixels);
3421                 pixels = NULL;
3422         }
3423
3424         mymiplevel = savemiplevel;
3425         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3426         {
3427                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3428                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3429                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3430                 Mem_Free(pixels);
3431                 pixels = NULL;
3432         }
3433
3434         mymiplevel = savemiplevel;
3435         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3436         {
3437                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3438                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3439                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3440                 Mem_Free(pixels);
3441                 pixels = NULL;
3442         }
3443
3444         if (basepixels)
3445                 Mem_Free(basepixels);
3446
3447         return skinframe;
3448 }
3449
3450 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3451 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3452 {
3453         int i;
3454         unsigned char *temp1, *temp2;
3455         skinframe_t *skinframe;
3456
3457         if (cls.state == ca_dedicated)
3458                 return NULL;
3459
3460         // if already loaded just return it, otherwise make a new skinframe
3461         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3462         if (skinframe && skinframe->base)
3463                 return skinframe;
3464
3465         skinframe->stain = NULL;
3466         skinframe->merged = NULL;
3467         skinframe->base = NULL;
3468         skinframe->pants = NULL;
3469         skinframe->shirt = NULL;
3470         skinframe->nmap = NULL;
3471         skinframe->gloss = NULL;
3472         skinframe->glow = NULL;
3473         skinframe->fog = NULL;
3474         skinframe->reflect = NULL;
3475         skinframe->hasalpha = false;
3476
3477         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3478         if (!skindata)
3479                 return NULL;
3480
3481         if (developer_loading.integer)
3482                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3483
3484         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3485         {
3486                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3487                 temp2 = temp1 + width * height * 4;
3488                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3489                 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);
3490                 Mem_Free(temp1);
3491         }
3492         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3493         if (textureflags & TEXF_ALPHA)
3494         {
3495                 for (i = 3;i < width * height * 4;i += 4)
3496                 {
3497                         if (skindata[i] < 255)
3498                         {
3499                                 skinframe->hasalpha = true;
3500                                 break;
3501                         }
3502                 }
3503                 if (r_loadfog && skinframe->hasalpha)
3504                 {
3505                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3506                         memcpy(fogpixels, skindata, width * height * 4);
3507                         for (i = 0;i < width * height * 4;i += 4)
3508                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3509                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3510                         Mem_Free(fogpixels);
3511                 }
3512         }
3513
3514         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3515         //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]);
3516
3517         return skinframe;
3518 }
3519
3520 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3521 {
3522         int i;
3523         int featuresmask;
3524         skinframe_t *skinframe;
3525
3526         if (cls.state == ca_dedicated)
3527                 return NULL;
3528
3529         // if already loaded just return it, otherwise make a new skinframe
3530         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3531         if (skinframe && skinframe->base)
3532                 return skinframe;
3533
3534         skinframe->stain = NULL;
3535         skinframe->merged = NULL;
3536         skinframe->base = NULL;
3537         skinframe->pants = NULL;
3538         skinframe->shirt = NULL;
3539         skinframe->nmap = NULL;
3540         skinframe->gloss = NULL;
3541         skinframe->glow = NULL;
3542         skinframe->fog = NULL;
3543         skinframe->reflect = NULL;
3544         skinframe->hasalpha = false;
3545
3546         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3547         if (!skindata)
3548                 return NULL;
3549
3550         if (developer_loading.integer)
3551                 Con_Printf("loading quake skin \"%s\"\n", name);
3552
3553         // 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)
3554         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3555         memcpy(skinframe->qpixels, skindata, width*height);
3556         skinframe->qwidth = width;
3557         skinframe->qheight = height;
3558
3559         featuresmask = 0;
3560         for (i = 0;i < width * height;i++)
3561                 featuresmask |= palette_featureflags[skindata[i]];
3562
3563         skinframe->hasalpha = false;
3564         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3565         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3566         skinframe->qgeneratemerged = true;
3567         skinframe->qgeneratebase = skinframe->qhascolormapping;
3568         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3569
3570         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3571         //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]);
3572
3573         return skinframe;
3574 }
3575
3576 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3577 {
3578         int width;
3579         int height;
3580         unsigned char *skindata;
3581
3582         if (!skinframe->qpixels)
3583                 return;
3584
3585         if (!skinframe->qhascolormapping)
3586                 colormapped = false;
3587
3588         if (colormapped)
3589         {
3590                 if (!skinframe->qgeneratebase)
3591                         return;
3592         }
3593         else
3594         {
3595                 if (!skinframe->qgeneratemerged)
3596                         return;
3597         }
3598
3599         width = skinframe->qwidth;
3600         height = skinframe->qheight;
3601         skindata = skinframe->qpixels;
3602
3603         if (skinframe->qgeneratenmap)
3604         {
3605                 unsigned char *temp1, *temp2;
3606                 skinframe->qgeneratenmap = false;
3607                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3608                 temp2 = temp1 + width * height * 4;
3609                 // use either a custom palette or the quake palette
3610                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3611                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3612                 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);
3613                 Mem_Free(temp1);
3614         }
3615
3616         if (skinframe->qgenerateglow)
3617         {
3618                 skinframe->qgenerateglow = false;
3619                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3620         }
3621
3622         if (colormapped)
3623         {
3624                 skinframe->qgeneratebase = false;
3625                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3626                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3627                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3628         }
3629         else
3630         {
3631                 skinframe->qgeneratemerged = false;
3632                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3633         }
3634
3635         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3636         {
3637                 Mem_Free(skinframe->qpixels);
3638                 skinframe->qpixels = NULL;
3639         }
3640 }
3641
3642 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)
3643 {
3644         int i;
3645         skinframe_t *skinframe;
3646
3647         if (cls.state == ca_dedicated)
3648                 return NULL;
3649
3650         // if already loaded just return it, otherwise make a new skinframe
3651         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3652         if (skinframe && skinframe->base)
3653                 return skinframe;
3654
3655         skinframe->stain = NULL;
3656         skinframe->merged = NULL;
3657         skinframe->base = NULL;
3658         skinframe->pants = NULL;
3659         skinframe->shirt = NULL;
3660         skinframe->nmap = NULL;
3661         skinframe->gloss = NULL;
3662         skinframe->glow = NULL;
3663         skinframe->fog = NULL;
3664         skinframe->reflect = NULL;
3665         skinframe->hasalpha = false;
3666
3667         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3668         if (!skindata)
3669                 return NULL;
3670
3671         if (developer_loading.integer)
3672                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3673
3674         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3675         if (textureflags & TEXF_ALPHA)
3676         {
3677                 for (i = 0;i < width * height;i++)
3678                 {
3679                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3680                         {
3681                                 skinframe->hasalpha = true;
3682                                 break;
3683                         }
3684                 }
3685                 if (r_loadfog && skinframe->hasalpha)
3686                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3687         }
3688
3689         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3690         //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]);
3691
3692         return skinframe;
3693 }
3694
3695 skinframe_t *R_SkinFrame_LoadMissing(void)
3696 {
3697         skinframe_t *skinframe;
3698
3699         if (cls.state == ca_dedicated)
3700                 return NULL;
3701
3702         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3703         skinframe->stain = NULL;
3704         skinframe->merged = NULL;
3705         skinframe->base = NULL;
3706         skinframe->pants = NULL;
3707         skinframe->shirt = NULL;
3708         skinframe->nmap = NULL;
3709         skinframe->gloss = NULL;
3710         skinframe->glow = NULL;
3711         skinframe->fog = NULL;
3712         skinframe->reflect = NULL;
3713         skinframe->hasalpha = false;
3714
3715         skinframe->avgcolor[0] = rand() / RAND_MAX;
3716         skinframe->avgcolor[1] = rand() / RAND_MAX;
3717         skinframe->avgcolor[2] = rand() / RAND_MAX;
3718         skinframe->avgcolor[3] = 1;
3719
3720         return skinframe;
3721 }
3722
3723 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3724 typedef struct suffixinfo_s
3725 {
3726         const char *suffix;
3727         qboolean flipx, flipy, flipdiagonal;
3728 }
3729 suffixinfo_t;
3730 static suffixinfo_t suffix[3][6] =
3731 {
3732         {
3733                 {"px",   false, false, false},
3734                 {"nx",   false, false, false},
3735                 {"py",   false, false, false},
3736                 {"ny",   false, false, false},
3737                 {"pz",   false, false, false},
3738                 {"nz",   false, false, false}
3739         },
3740         {
3741                 {"posx", false, false, false},
3742                 {"negx", false, false, false},
3743                 {"posy", false, false, false},
3744                 {"negy", false, false, false},
3745                 {"posz", false, false, false},
3746                 {"negz", false, false, false}
3747         },
3748         {
3749                 {"rt",    true, false,  true},
3750                 {"lf",   false,  true,  true},
3751                 {"ft",    true,  true, false},
3752                 {"bk",   false, false, false},
3753                 {"up",    true, false,  true},
3754                 {"dn",    true, false,  true}
3755         }
3756 };
3757
3758 static int componentorder[4] = {0, 1, 2, 3};
3759
3760 rtexture_t *R_LoadCubemap(const char *basename)
3761 {
3762         int i, j, cubemapsize;
3763         unsigned char *cubemappixels, *image_buffer;
3764         rtexture_t *cubemaptexture;
3765         char name[256];
3766         // must start 0 so the first loadimagepixels has no requested width/height
3767         cubemapsize = 0;
3768         cubemappixels = NULL;
3769         cubemaptexture = NULL;
3770         // keep trying different suffix groups (posx, px, rt) until one loads
3771         for (j = 0;j < 3 && !cubemappixels;j++)
3772         {
3773                 // load the 6 images in the suffix group
3774                 for (i = 0;i < 6;i++)
3775                 {
3776                         // generate an image name based on the base and and suffix
3777                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3778                         // load it
3779                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3780                         {
3781                                 // an image loaded, make sure width and height are equal
3782                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3783                                 {
3784                                         // if this is the first image to load successfully, allocate the cubemap memory
3785                                         if (!cubemappixels && image_width >= 1)
3786                                         {
3787                                                 cubemapsize = image_width;
3788                                                 // note this clears to black, so unavailable sides are black
3789                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3790                                         }
3791                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3792                                         if (cubemappixels)
3793                                                 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);
3794                                 }
3795                                 else
3796                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3797                                 // free the image
3798                                 Mem_Free(image_buffer);
3799                         }
3800                 }
3801         }
3802         // if a cubemap loaded, upload it
3803         if (cubemappixels)
3804         {
3805                 if (developer_loading.integer)
3806                         Con_Printf("loading cubemap \"%s\"\n", basename);
3807
3808                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3809                 Mem_Free(cubemappixels);
3810         }
3811         else
3812         {
3813                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3814                 if (developer_loading.integer)
3815                 {
3816                         Con_Printf("(tried tried images ");
3817                         for (j = 0;j < 3;j++)
3818                                 for (i = 0;i < 6;i++)
3819                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3820                         Con_Print(" and was unable to find any of them).\n");
3821                 }
3822         }
3823         return cubemaptexture;
3824 }
3825
3826 rtexture_t *R_GetCubemap(const char *basename)
3827 {
3828         int i;
3829         for (i = 0;i < r_texture_numcubemaps;i++)
3830                 if (r_texture_cubemaps[i] != NULL)
3831                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3832                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3833         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3834                 return r_texture_whitecube;
3835         r_texture_numcubemaps++;
3836         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3837         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3838         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3839         return r_texture_cubemaps[i]->texture;
3840 }
3841
3842 void R_FreeCubemap(const char *basename)
3843 {
3844         int i;
3845
3846         for (i = 0;i < r_texture_numcubemaps;i++)
3847         {
3848                 if (r_texture_cubemaps[i] != NULL)
3849                 {
3850                         if (r_texture_cubemaps[i]->texture)
3851                         {
3852                                 if (developer_loading.integer)
3853                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3854                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3855                                 Mem_Free(r_texture_cubemaps[i]);
3856                                 r_texture_cubemaps[i] = NULL;
3857                         }
3858                 }
3859         }
3860 }
3861
3862 void R_FreeCubemaps(void)
3863 {
3864         int i;
3865         for (i = 0;i < r_texture_numcubemaps;i++)
3866         {
3867                 if (developer_loading.integer)
3868                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3869                 if (r_texture_cubemaps[i] != NULL)
3870                 {
3871                         if (r_texture_cubemaps[i]->texture)
3872                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3873                         Mem_Free(r_texture_cubemaps[i]);
3874                 }
3875         }
3876         r_texture_numcubemaps = 0;
3877 }
3878
3879 void R_Main_FreeViewCache(void)
3880 {
3881         if (r_refdef.viewcache.entityvisible)
3882                 Mem_Free(r_refdef.viewcache.entityvisible);
3883         if (r_refdef.viewcache.world_pvsbits)
3884                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3885         if (r_refdef.viewcache.world_leafvisible)
3886                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3887         if (r_refdef.viewcache.world_surfacevisible)
3888                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3889         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3890 }
3891
3892 void R_Main_ResizeViewCache(void)
3893 {
3894         int numentities = r_refdef.scene.numentities;
3895         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3896         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3897         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3898         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3899         if (r_refdef.viewcache.maxentities < numentities)
3900         {
3901                 r_refdef.viewcache.maxentities = numentities;
3902                 if (r_refdef.viewcache.entityvisible)
3903                         Mem_Free(r_refdef.viewcache.entityvisible);
3904                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3905         }
3906         if (r_refdef.viewcache.world_numclusters != numclusters)
3907         {
3908                 r_refdef.viewcache.world_numclusters = numclusters;
3909                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3910                 if (r_refdef.viewcache.world_pvsbits)
3911                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3912                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3913         }
3914         if (r_refdef.viewcache.world_numleafs != numleafs)
3915         {
3916                 r_refdef.viewcache.world_numleafs = numleafs;
3917                 if (r_refdef.viewcache.world_leafvisible)
3918                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3919                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3920         }
3921         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3922         {
3923                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3924                 if (r_refdef.viewcache.world_surfacevisible)
3925                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3926                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3927         }
3928 }
3929
3930 extern rtexture_t *loadingscreentexture;
3931 void gl_main_start(void)
3932 {
3933         loadingscreentexture = NULL;
3934         r_texture_blanknormalmap = NULL;
3935         r_texture_white = NULL;
3936         r_texture_grey128 = NULL;
3937         r_texture_black = NULL;
3938         r_texture_whitecube = NULL;
3939         r_texture_normalizationcube = NULL;
3940         r_texture_fogattenuation = NULL;
3941         r_texture_fogheighttexture = NULL;
3942         r_texture_gammaramps = NULL;
3943         r_texture_numcubemaps = 0;
3944
3945         r_loaddds = r_texture_dds_load.integer != 0;
3946         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3947
3948         switch(vid.renderpath)
3949         {
3950         case RENDERPATH_GL20:
3951         case RENDERPATH_D3D9:
3952         case RENDERPATH_D3D10:
3953         case RENDERPATH_D3D11:
3954         case RENDERPATH_SOFT:
3955         case RENDERPATH_GLES2:
3956                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3957                 Cvar_SetValueQuick(&gl_combine, 1);
3958                 Cvar_SetValueQuick(&r_glsl, 1);
3959                 r_loadnormalmap = true;
3960                 r_loadgloss = true;
3961                 r_loadfog = false;
3962                 break;
3963         case RENDERPATH_GL13:
3964         case RENDERPATH_GLES1:
3965                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3966                 Cvar_SetValueQuick(&gl_combine, 1);
3967                 Cvar_SetValueQuick(&r_glsl, 0);
3968                 r_loadnormalmap = false;
3969                 r_loadgloss = false;
3970                 r_loadfog = true;
3971                 break;
3972         case RENDERPATH_GL11:
3973                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3974                 Cvar_SetValueQuick(&gl_combine, 0);
3975                 Cvar_SetValueQuick(&r_glsl, 0);
3976                 r_loadnormalmap = false;
3977                 r_loadgloss = false;
3978                 r_loadfog = true;
3979                 break;
3980         }
3981
3982         R_AnimCache_Free();
3983         R_FrameData_Reset();
3984
3985         r_numqueries = 0;
3986         r_maxqueries = 0;
3987         memset(r_queries, 0, sizeof(r_queries));
3988
3989         r_qwskincache = NULL;
3990         r_qwskincache_size = 0;
3991
3992         // due to caching of texture_t references, the collision cache must be reset
3993         Collision_Cache_Reset(true);
3994
3995         // set up r_skinframe loading system for textures
3996         memset(&r_skinframe, 0, sizeof(r_skinframe));
3997         r_skinframe.loadsequence = 1;
3998         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3999
4000         r_main_texturepool = R_AllocTexturePool();
4001         R_BuildBlankTextures();
4002         R_BuildNoTexture();
4003         if (vid.support.arb_texture_cube_map)
4004         {
4005                 R_BuildWhiteCube();
4006                 R_BuildNormalizationCube();
4007         }
4008         r_texture_fogattenuation = NULL;
4009         r_texture_fogheighttexture = NULL;
4010         r_texture_gammaramps = NULL;
4011         //r_texture_fogintensity = NULL;
4012         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4013         memset(&r_waterstate, 0, sizeof(r_waterstate));
4014         r_glsl_permutation = NULL;
4015         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4016         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4017         glslshaderstring = NULL;
4018 #ifdef SUPPORTD3D
4019         r_hlsl_permutation = NULL;
4020         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4021         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4022 #endif
4023         hlslshaderstring = NULL;
4024         memset(&r_svbsp, 0, sizeof (r_svbsp));
4025
4026         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4027         r_texture_numcubemaps = 0;
4028
4029         r_refdef.fogmasktable_density = 0;
4030 }
4031
4032 void gl_main_shutdown(void)
4033 {
4034         R_AnimCache_Free();
4035         R_FrameData_Reset();
4036
4037         R_Main_FreeViewCache();
4038
4039         switch(vid.renderpath)
4040         {
4041         case RENDERPATH_GL11:
4042         case RENDERPATH_GL13:
4043         case RENDERPATH_GL20:
4044         case RENDERPATH_GLES1:
4045         case RENDERPATH_GLES2:
4046                 if (r_maxqueries)
4047                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4048                 break;
4049         case RENDERPATH_D3D9:
4050                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4051                 break;
4052         case RENDERPATH_D3D10:
4053                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4054                 break;
4055         case RENDERPATH_D3D11:
4056                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4057                 break;
4058         case RENDERPATH_SOFT:
4059                 break;
4060         }
4061
4062         r_numqueries = 0;
4063         r_maxqueries = 0;
4064         memset(r_queries, 0, sizeof(r_queries));
4065
4066         r_qwskincache = NULL;
4067         r_qwskincache_size = 0;
4068
4069         // clear out the r_skinframe state
4070         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4071         memset(&r_skinframe, 0, sizeof(r_skinframe));
4072
4073         if (r_svbsp.nodes)
4074                 Mem_Free(r_svbsp.nodes);
4075         memset(&r_svbsp, 0, sizeof (r_svbsp));
4076         R_FreeTexturePool(&r_main_texturepool);
4077         loadingscreentexture = NULL;
4078         r_texture_blanknormalmap = NULL;
4079         r_texture_white = NULL;
4080         r_texture_grey128 = NULL;
4081         r_texture_black = NULL;
4082         r_texture_whitecube = NULL;
4083         r_texture_normalizationcube = NULL;
4084         r_texture_fogattenuation = NULL;
4085         r_texture_fogheighttexture = NULL;
4086         r_texture_gammaramps = NULL;
4087         r_texture_numcubemaps = 0;
4088         //r_texture_fogintensity = NULL;
4089         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4090         memset(&r_waterstate, 0, sizeof(r_waterstate));
4091         R_GLSL_Restart_f();
4092
4093         r_glsl_permutation = NULL;
4094         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4095         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4096         glslshaderstring = NULL;
4097 #ifdef SUPPORTD3D
4098         r_hlsl_permutation = NULL;
4099         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4100         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4101 #endif
4102         hlslshaderstring = NULL;
4103 }
4104
4105 extern void CL_ParseEntityLump(char *entitystring);
4106 void gl_main_newmap(void)
4107 {
4108         // FIXME: move this code to client
4109         char *entities, entname[MAX_QPATH];
4110         if (r_qwskincache)
4111                 Mem_Free(r_qwskincache);
4112         r_qwskincache = NULL;
4113         r_qwskincache_size = 0;
4114         if (cl.worldmodel)
4115         {
4116                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4117                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4118                 {
4119                         CL_ParseEntityLump(entities);
4120                         Mem_Free(entities);
4121                         return;
4122                 }
4123                 if (cl.worldmodel->brush.entities)
4124                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4125         }
4126         R_Main_FreeViewCache();
4127
4128         R_FrameData_Reset();
4129 }
4130
4131 void GL_Main_Init(void)
4132 {
4133         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4134
4135         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4136         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4137         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4138         if (gamemode == GAME_NEHAHRA)
4139         {
4140                 Cvar_RegisterVariable (&gl_fogenable);
4141                 Cvar_RegisterVariable (&gl_fogdensity);
4142                 Cvar_RegisterVariable (&gl_fogred);
4143                 Cvar_RegisterVariable (&gl_foggreen);
4144                 Cvar_RegisterVariable (&gl_fogblue);
4145                 Cvar_RegisterVariable (&gl_fogstart);
4146                 Cvar_RegisterVariable (&gl_fogend);
4147                 Cvar_RegisterVariable (&gl_skyclip);
4148         }
4149         Cvar_RegisterVariable(&r_motionblur);
4150         Cvar_RegisterVariable(&r_damageblur);
4151         Cvar_RegisterVariable(&r_motionblur_averaging);
4152         Cvar_RegisterVariable(&r_motionblur_randomize);
4153         Cvar_RegisterVariable(&r_motionblur_minblur);
4154         Cvar_RegisterVariable(&r_motionblur_maxblur);
4155         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4156         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4157         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4158         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4159         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4160         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4161         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4162         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4163         Cvar_RegisterVariable(&r_equalize_entities_by);
4164         Cvar_RegisterVariable(&r_equalize_entities_to);
4165         Cvar_RegisterVariable(&r_depthfirst);
4166         Cvar_RegisterVariable(&r_useinfinitefarclip);
4167         Cvar_RegisterVariable(&r_farclip_base);
4168         Cvar_RegisterVariable(&r_farclip_world);
4169         Cvar_RegisterVariable(&r_nearclip);
4170         Cvar_RegisterVariable(&r_deformvertexes);
4171         Cvar_RegisterVariable(&r_transparent);
4172         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4173         Cvar_RegisterVariable(&r_showoverdraw);
4174         Cvar_RegisterVariable(&r_showbboxes);
4175         Cvar_RegisterVariable(&r_showsurfaces);
4176         Cvar_RegisterVariable(&r_showtris);
4177         Cvar_RegisterVariable(&r_shownormals);
4178         Cvar_RegisterVariable(&r_showlighting);
4179         Cvar_RegisterVariable(&r_showshadowvolumes);
4180         Cvar_RegisterVariable(&r_showcollisionbrushes);
4181         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4182         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4183         Cvar_RegisterVariable(&r_showdisabledepthtest);
4184         Cvar_RegisterVariable(&r_drawportals);
4185         Cvar_RegisterVariable(&r_drawentities);
4186         Cvar_RegisterVariable(&r_draw2d);
4187         Cvar_RegisterVariable(&r_drawworld);
4188         Cvar_RegisterVariable(&r_cullentities_trace);
4189         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4190         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4191         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4192         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4193         Cvar_RegisterVariable(&r_drawviewmodel);
4194         Cvar_RegisterVariable(&r_drawexteriormodel);
4195         Cvar_RegisterVariable(&r_speeds);
4196         Cvar_RegisterVariable(&r_fullbrights);
4197         Cvar_RegisterVariable(&r_wateralpha);
4198         Cvar_RegisterVariable(&r_dynamic);
4199         Cvar_RegisterVariable(&r_fakelight);
4200         Cvar_RegisterVariable(&r_fakelight_intensity);
4201         Cvar_RegisterVariable(&r_fullbright);
4202         Cvar_RegisterVariable(&r_shadows);
4203         Cvar_RegisterVariable(&r_shadows_darken);
4204         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4205         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4206         Cvar_RegisterVariable(&r_shadows_throwdistance);
4207         Cvar_RegisterVariable(&r_shadows_throwdirection);
4208         Cvar_RegisterVariable(&r_shadows_focus);
4209         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4210         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4211         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4212         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4213         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4214         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4215         Cvar_RegisterVariable(&r_fog_exp2);
4216         Cvar_RegisterVariable(&r_fog_clear);
4217         Cvar_RegisterVariable(&r_drawfog);
4218         Cvar_RegisterVariable(&r_transparentdepthmasking);
4219         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4220         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4221         Cvar_RegisterVariable(&r_texture_dds_load);
4222         Cvar_RegisterVariable(&r_texture_dds_save);
4223         Cvar_RegisterVariable(&r_textureunits);
4224         Cvar_RegisterVariable(&gl_combine);
4225         Cvar_RegisterVariable(&r_viewfbo);
4226         Cvar_RegisterVariable(&r_viewscale);
4227         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4228         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4229         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4230         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4231         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4232         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4233         Cvar_RegisterVariable(&r_glsl);
4234         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4235         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4236         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4237         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4238         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4239         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4240         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4241         Cvar_RegisterVariable(&r_glsl_postprocess);
4242         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4243         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4244         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4245         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4246         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4247         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4248         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4249         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4250
4251         Cvar_RegisterVariable(&r_water);
4252         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4253         Cvar_RegisterVariable(&r_water_clippingplanebias);
4254         Cvar_RegisterVariable(&r_water_refractdistort);
4255         Cvar_RegisterVariable(&r_water_reflectdistort);
4256         Cvar_RegisterVariable(&r_water_scissormode);
4257         Cvar_RegisterVariable(&r_water_lowquality);
4258
4259         Cvar_RegisterVariable(&r_lerpsprites);
4260         Cvar_RegisterVariable(&r_lerpmodels);
4261         Cvar_RegisterVariable(&r_lerplightstyles);
4262         Cvar_RegisterVariable(&r_waterscroll);
4263         Cvar_RegisterVariable(&r_bloom);
4264         Cvar_RegisterVariable(&r_bloom_colorscale);
4265         Cvar_RegisterVariable(&r_bloom_brighten);
4266         Cvar_RegisterVariable(&r_bloom_blur);
4267         Cvar_RegisterVariable(&r_bloom_resolution);
4268         Cvar_RegisterVariable(&r_bloom_colorexponent);
4269         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4270         Cvar_RegisterVariable(&r_hdr);
4271         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4272         Cvar_RegisterVariable(&r_hdr_glowintensity);
4273         Cvar_RegisterVariable(&r_hdr_range);
4274         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4275         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4276         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4277         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4278         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4279         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4280         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4281         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4282         Cvar_RegisterVariable(&developer_texturelogging);
4283         Cvar_RegisterVariable(&gl_lightmaps);
4284         Cvar_RegisterVariable(&r_test);
4285         Cvar_RegisterVariable(&r_glsl_saturation);
4286         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4287         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4288         Cvar_RegisterVariable(&r_framedatasize);
4289         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4290                 Cvar_SetValue("r_fullbrights", 0);
4291         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4292 }
4293
4294 extern void R_Textures_Init(void);
4295 extern void GL_Draw_Init(void);
4296 extern void GL_Main_Init(void);
4297 extern void R_Shadow_Init(void);
4298 extern void R_Sky_Init(void);
4299 extern void GL_Surf_Init(void);
4300 extern void R_Particles_Init(void);
4301 extern void R_Explosion_Init(void);
4302 extern void gl_backend_init(void);
4303 extern void Sbar_Init(void);
4304 extern void R_LightningBeams_Init(void);
4305 extern void Mod_RenderInit(void);
4306 extern void Font_Init(void);
4307
4308 void Render_Init(void)
4309 {
4310         gl_backend_init();
4311         R_Textures_Init();
4312         GL_Main_Init();
4313         Font_Init();
4314         GL_Draw_Init();
4315         R_Shadow_Init();
4316         R_Sky_Init();
4317         GL_Surf_Init();
4318         Sbar_Init();
4319         R_Particles_Init();
4320         R_Explosion_Init();
4321         R_LightningBeams_Init();
4322         Mod_RenderInit();
4323 }
4324
4325 /*
4326 ===============
4327 GL_Init
4328 ===============
4329 */
4330 extern char *ENGINE_EXTENSIONS;
4331 void GL_Init (void)
4332 {
4333         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4334         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4335         gl_version = (const char *)qglGetString(GL_VERSION);
4336         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4337
4338         if (!gl_extensions)
4339                 gl_extensions = "";
4340         if (!gl_platformextensions)
4341                 gl_platformextensions = "";
4342
4343         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4344         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4345         Con_Printf("GL_VERSION: %s\n", gl_version);
4346         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4347         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4348
4349         VID_CheckExtensions();
4350
4351         // LordHavoc: report supported extensions
4352         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4353
4354         // clear to black (loading plaque will be seen over this)
4355         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4356 }
4357
4358 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4359 {
4360         int i;
4361         mplane_t *p;
4362         if (r_trippy.integer)
4363                 return false;
4364         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4365         {
4366                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4367                 if (i == 4)
4368                         continue;
4369                 p = r_refdef.view.frustum + i;
4370                 switch(p->signbits)
4371                 {
4372                 default:
4373                 case 0:
4374                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4375                                 return true;
4376                         break;
4377                 case 1:
4378                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4379                                 return true;
4380                         break;
4381                 case 2:
4382                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4383                                 return true;
4384                         break;
4385                 case 3:
4386                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4387                                 return true;
4388                         break;
4389                 case 4:
4390                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4391                                 return true;
4392                         break;
4393                 case 5:
4394                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4395                                 return true;
4396                         break;
4397                 case 6:
4398                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4399                                 return true;
4400                         break;
4401                 case 7:
4402                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4403                                 return true;
4404                         break;
4405                 }
4406         }
4407         return false;
4408 }
4409
4410 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4411 {
4412         int i;
4413         const mplane_t *p;
4414         if (r_trippy.integer)
4415                 return false;
4416         for (i = 0;i < numplanes;i++)
4417         {
4418                 p = planes + i;
4419                 switch(p->signbits)
4420                 {
4421                 default:
4422                 case 0:
4423                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4424                                 return true;
4425                         break;
4426                 case 1:
4427                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4428                                 return true;
4429                         break;
4430                 case 2:
4431                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4432                                 return true;
4433                         break;
4434                 case 3:
4435                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4436                                 return true;
4437                         break;
4438                 case 4:
4439                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4440                                 return true;
4441                         break;
4442                 case 5:
4443                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4444                                 return true;
4445                         break;
4446                 case 6:
4447                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4448                                 return true;
4449                         break;
4450                 case 7:
4451                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4452                                 return true;
4453                         break;
4454                 }
4455         }
4456         return false;
4457 }
4458
4459 //==================================================================================
4460
4461 // LordHavoc: this stores temporary data used within the same frame
4462
4463 typedef struct r_framedata_mem_s
4464 {
4465         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4466         size_t size; // how much usable space
4467         size_t current; // how much space in use
4468         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4469         size_t wantedsize; // how much space was allocated
4470         unsigned char *data; // start of real data (16byte aligned)
4471 }
4472 r_framedata_mem_t;
4473
4474 static r_framedata_mem_t *r_framedata_mem;
4475
4476 void R_FrameData_Reset(void)
4477 {
4478         while (r_framedata_mem)
4479         {
4480                 r_framedata_mem_t *next = r_framedata_mem->purge;
4481                 Mem_Free(r_framedata_mem);
4482                 r_framedata_mem = next;
4483         }
4484 }
4485
4486 void R_FrameData_Resize(void)
4487 {
4488         size_t wantedsize;
4489         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4490         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4491         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4492         {
4493                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4494                 newmem->wantedsize = wantedsize;
4495                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4496                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4497                 newmem->current = 0;
4498                 newmem->mark = 0;
4499                 newmem->purge = r_framedata_mem;
4500                 r_framedata_mem = newmem;
4501         }
4502 }
4503
4504 void R_FrameData_NewFrame(void)
4505 {
4506         R_FrameData_Resize();
4507         if (!r_framedata_mem)
4508                 return;
4509         // if we ran out of space on the last frame, free the old memory now
4510         while (r_framedata_mem->purge)
4511         {
4512                 // repeatedly remove the second item in the list, leaving only head
4513                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4514                 Mem_Free(r_framedata_mem->purge);
4515                 r_framedata_mem->purge = next;
4516         }
4517         // reset the current mem pointer
4518         r_framedata_mem->current = 0;
4519         r_framedata_mem->mark = 0;
4520 }
4521
4522 void *R_FrameData_Alloc(size_t size)
4523 {
4524         void *data;
4525
4526         // align to 16 byte boundary - the data pointer is already aligned, so we
4527         // only need to ensure the size of every allocation is also aligned
4528         size = (size + 15) & ~15;
4529
4530         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4531         {
4532                 // emergency - we ran out of space, allocate more memory
4533                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4534                 R_FrameData_Resize();
4535         }
4536
4537         data = r_framedata_mem->data + r_framedata_mem->current;
4538         r_framedata_mem->current += size;
4539
4540         // count the usage for stats
4541         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4542         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4543
4544         return (void *)data;
4545 }
4546
4547 void *R_FrameData_Store(size_t size, void *data)
4548 {
4549         void *d = R_FrameData_Alloc(size);
4550         if (d && data)
4551                 memcpy(d, data, size);
4552         return d;
4553 }
4554
4555 void R_FrameData_SetMark(void)
4556 {
4557         if (!r_framedata_mem)
4558                 return;
4559         r_framedata_mem->mark = r_framedata_mem->current;
4560 }
4561
4562 void R_FrameData_ReturnToMark(void)
4563 {
4564         if (!r_framedata_mem)
4565                 return;
4566         r_framedata_mem->current = r_framedata_mem->mark;
4567 }
4568
4569 //==================================================================================
4570
4571 // LordHavoc: animcache originally written by Echon, rewritten since then
4572
4573 /**
4574  * Animation cache prevents re-generating mesh data for an animated model
4575  * multiple times in one frame for lighting, shadowing, reflections, etc.
4576  */
4577
4578 void R_AnimCache_Free(void)
4579 {
4580 }
4581
4582 void R_AnimCache_ClearCache(void)
4583 {
4584         int i;
4585         entity_render_t *ent;
4586
4587         for (i = 0;i < r_refdef.scene.numentities;i++)
4588         {
4589                 ent = r_refdef.scene.entities[i];
4590                 ent->animcache_vertex3f = NULL;
4591                 ent->animcache_normal3f = NULL;
4592                 ent->animcache_svector3f = NULL;
4593                 ent->animcache_tvector3f = NULL;
4594                 ent->animcache_vertexmesh = NULL;
4595                 ent->animcache_vertex3fbuffer = NULL;
4596                 ent->animcache_vertexmeshbuffer = NULL;
4597         }
4598 }
4599
4600 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4601 {
4602         int i;
4603
4604         // check if we need the meshbuffers
4605         if (!vid.useinterleavedarrays)
4606                 return;
4607
4608         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4609                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4610         // TODO: upload vertex3f buffer?
4611         if (ent->animcache_vertexmesh)
4612         {
4613                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4614                 for (i = 0;i < numvertices;i++)
4615                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4616                 if (ent->animcache_svector3f)
4617                         for (i = 0;i < numvertices;i++)
4618                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4619                 if (ent->animcache_tvector3f)
4620                         for (i = 0;i < numvertices;i++)
4621                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4622                 if (ent->animcache_normal3f)
4623                         for (i = 0;i < numvertices;i++)
4624                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4625                 // TODO: upload vertexmeshbuffer?
4626         }
4627 }
4628
4629 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4630 {
4631         dp_model_t *model = ent->model;
4632         int numvertices;
4633         // see if it's already cached this frame
4634         if (ent->animcache_vertex3f)
4635         {
4636                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4637                 if (wantnormals || wanttangents)
4638                 {
4639                         if (ent->animcache_normal3f)
4640                                 wantnormals = false;
4641                         if (ent->animcache_svector3f)
4642                                 wanttangents = false;
4643                         if (wantnormals || wanttangents)
4644                         {
4645                                 numvertices = model->surfmesh.num_vertices;
4646                                 if (wantnormals)
4647                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4648                                 if (wanttangents)
4649                                 {
4650                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4651                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4652                                 }
4653                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4654                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4655                         }
4656                 }
4657         }
4658         else
4659         {
4660                 // see if this ent is worth caching
4661                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4662                         return false;
4663                 // get some memory for this entity and generate mesh data
4664                 numvertices = model->surfmesh.num_vertices;
4665                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4666                 if (wantnormals)
4667                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4668                 if (wanttangents)
4669                 {
4670                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4671                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4672                 }
4673                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4674                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4675         }
4676         return true;
4677 }
4678
4679 void R_AnimCache_CacheVisibleEntities(void)
4680 {
4681         int i;
4682         qboolean wantnormals = true;
4683         qboolean wanttangents = !r_showsurfaces.integer;
4684
4685         switch(vid.renderpath)
4686         {
4687         case RENDERPATH_GL20:
4688         case RENDERPATH_D3D9:
4689         case RENDERPATH_D3D10:
4690         case RENDERPATH_D3D11:
4691         case RENDERPATH_GLES2:
4692                 break;
4693         case RENDERPATH_GL11:
4694         case RENDERPATH_GL13:
4695         case RENDERPATH_GLES1:
4696                 wanttangents = false;
4697                 break;
4698         case RENDERPATH_SOFT:
4699                 break;
4700         }
4701
4702         if (r_shownormals.integer)
4703                 wanttangents = wantnormals = true;
4704
4705         // TODO: thread this
4706         // NOTE: R_PrepareRTLights() also caches entities
4707
4708         for (i = 0;i < r_refdef.scene.numentities;i++)
4709                 if (r_refdef.viewcache.entityvisible[i])
4710                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4711 }
4712
4713 //==================================================================================
4714
4715 extern cvar_t r_overheadsprites_pushback;
4716
4717 static void R_View_UpdateEntityLighting (void)
4718 {
4719         int i;
4720         entity_render_t *ent;
4721         vec3_t tempdiffusenormal, avg;
4722         vec_t f, fa, fd, fdd;
4723         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4724
4725         for (i = 0;i < r_refdef.scene.numentities;i++)
4726         {
4727                 ent = r_refdef.scene.entities[i];
4728
4729                 // skip unseen models
4730                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4731                         continue;
4732
4733                 // skip bsp models
4734                 if (ent->model && ent->model->brush.num_leafs)
4735                 {
4736                         // TODO: use modellight for r_ambient settings on world?
4737                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4738                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4739                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4740                         continue;
4741                 }
4742
4743                 // fetch the lighting from the worldmodel data
4744                 VectorClear(ent->modellight_ambient);
4745                 VectorClear(ent->modellight_diffuse);
4746                 VectorClear(tempdiffusenormal);
4747                 if (ent->flags & RENDER_LIGHT)
4748                 {
4749                         vec3_t org;
4750                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4751
4752                         // complete lightning for lit sprites
4753                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4754                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4755                         {
4756                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4757                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4758                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4759                         }
4760                         else
4761                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4762
4763                         if(ent->flags & RENDER_EQUALIZE)
4764                         {
4765                                 // first fix up ambient lighting...
4766                                 if(r_equalize_entities_minambient.value > 0)
4767                                 {
4768                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4769                                         if(fd > 0)
4770                                         {
4771                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4772                                                 if(fa < r_equalize_entities_minambient.value * fd)
4773                                                 {
4774                                                         // solve:
4775                                                         //   fa'/fd' = minambient
4776                                                         //   fa'+0.25*fd' = fa+0.25*fd
4777                                                         //   ...
4778                                                         //   fa' = fd' * minambient
4779                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4780                                                         //   ...
4781                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4782                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4783                                                         //   ...
4784                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4785                                                         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
4786                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4787                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4788                                                 }
4789                                         }
4790                                 }
4791
4792                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4793                                 {
4794                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4795                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4796                                         f = fa + 0.25 * fd;
4797                                         if(f > 0)
4798                                         {
4799                                                 // adjust brightness and saturation to target
4800                                                 avg[0] = avg[1] = avg[2] = fa / f;
4801                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4802                                                 avg[0] = avg[1] = avg[2] = fd / f;
4803                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4804                                         }
4805                                 }
4806                         }
4807                 }
4808                 else // highly rare
4809                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4810
4811                 // move the light direction into modelspace coordinates for lighting code
4812                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4813                 if(VectorLength2(ent->modellight_lightdir) == 0)
4814                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4815                 VectorNormalize(ent->modellight_lightdir);
4816         }
4817 }
4818
4819 #define MAX_LINEOFSIGHTTRACES 64
4820
4821 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4822 {
4823         int i;
4824         vec3_t boxmins, boxmaxs;
4825         vec3_t start;
4826         vec3_t end;
4827         dp_model_t *model = r_refdef.scene.worldmodel;
4828
4829         if (!model || !model->brush.TraceLineOfSight)
4830                 return true;
4831
4832         // expand the box a little
4833         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4834         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4835         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4836         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4837         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4838         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4839
4840         // return true if eye is inside enlarged box
4841         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4842                 return true;
4843
4844         // try center
4845         VectorCopy(eye, start);
4846         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4847         if (model->brush.TraceLineOfSight(model, start, end))
4848                 return true;
4849
4850         // try various random positions
4851         for (i = 0;i < numsamples;i++)
4852         {
4853                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4854                 if (model->brush.TraceLineOfSight(model, start, end))
4855                         return true;
4856         }
4857
4858         return false;
4859 }
4860
4861
4862 static void R_View_UpdateEntityVisible (void)
4863 {
4864         int i;
4865         int renderimask;
4866         int samples;
4867         entity_render_t *ent;
4868
4869         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4870                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4871                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4872                 :                                                          RENDER_EXTERIORMODEL;
4873         if (!r_drawviewmodel.integer)
4874                 renderimask |= RENDER_VIEWMODEL;
4875         if (!r_drawexteriormodel.integer)
4876                 renderimask |= RENDER_EXTERIORMODEL;
4877         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4878         {
4879                 // worldmodel can check visibility
4880                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4881                 for (i = 0;i < r_refdef.scene.numentities;i++)
4882                 {
4883                         ent = r_refdef.scene.entities[i];
4884                         if (!(ent->flags & renderimask))
4885                         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)))
4886                         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))
4887                                 r_refdef.viewcache.entityvisible[i] = true;
4888                 }
4889         }
4890         else
4891         {
4892                 // no worldmodel or it can't check visibility
4893                 for (i = 0;i < r_refdef.scene.numentities;i++)
4894                 {
4895                         ent = r_refdef.scene.entities[i];
4896                         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));
4897                 }
4898         }
4899         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4900                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4901         {
4902                 for (i = 0;i < r_refdef.scene.numentities;i++)
4903                 {
4904                         if (!r_refdef.viewcache.entityvisible[i])
4905                                 continue;
4906                         ent = r_refdef.scene.entities[i];
4907                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4908                         {
4909                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4910                                 if (samples < 0)
4911                                         continue; // temp entities do pvs only
4912                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4913                                         ent->last_trace_visibility = realtime;
4914                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4915                                         r_refdef.viewcache.entityvisible[i] = 0;
4916                         }
4917                 }
4918         }
4919 }
4920
4921 /// only used if skyrendermasked, and normally returns false
4922 int R_DrawBrushModelsSky (void)
4923 {
4924         int i, sky;
4925         entity_render_t *ent;
4926
4927         sky = false;
4928         for (i = 0;i < r_refdef.scene.numentities;i++)
4929         {
4930                 if (!r_refdef.viewcache.entityvisible[i])
4931                         continue;
4932                 ent = r_refdef.scene.entities[i];
4933                 if (!ent->model || !ent->model->DrawSky)
4934                         continue;
4935                 ent->model->DrawSky(ent);
4936                 sky = true;
4937         }
4938         return sky;
4939 }
4940
4941 static void R_DrawNoModel(entity_render_t *ent);
4942 static void R_DrawModels(void)
4943 {
4944         int i;
4945         entity_render_t *ent;
4946
4947         for (i = 0;i < r_refdef.scene.numentities;i++)
4948         {
4949                 if (!r_refdef.viewcache.entityvisible[i])
4950                         continue;
4951                 ent = r_refdef.scene.entities[i];
4952                 r_refdef.stats.entities++;
4953                 /*
4954                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4955                 {
4956                         vec3_t f, l, u, o;
4957                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4958                         Con_Printf("R_DrawModels\n");
4959                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4960                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4961                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4962                 }
4963                 */
4964                 if (ent->model && ent->model->Draw != NULL)
4965                         ent->model->Draw(ent);
4966                 else
4967                         R_DrawNoModel(ent);
4968         }
4969 }
4970
4971 static void R_DrawModelsDepth(void)
4972 {
4973         int i;
4974         entity_render_t *ent;
4975
4976         for (i = 0;i < r_refdef.scene.numentities;i++)
4977         {
4978                 if (!r_refdef.viewcache.entityvisible[i])
4979                         continue;
4980                 ent = r_refdef.scene.entities[i];
4981                 if (ent->model && ent->model->DrawDepth != NULL)
4982                         ent->model->DrawDepth(ent);
4983         }
4984 }
4985
4986 static void R_DrawModelsDebug(void)
4987 {
4988         int i;
4989         entity_render_t *ent;
4990
4991         for (i = 0;i < r_refdef.scene.numentities;i++)
4992         {
4993                 if (!r_refdef.viewcache.entityvisible[i])
4994                         continue;
4995                 ent = r_refdef.scene.entities[i];
4996                 if (ent->model && ent->model->DrawDebug != NULL)
4997                         ent->model->DrawDebug(ent);
4998         }
4999 }
5000
5001 static void R_DrawModelsAddWaterPlanes(void)
5002 {
5003         int i;
5004         entity_render_t *ent;
5005
5006         for (i = 0;i < r_refdef.scene.numentities;i++)
5007         {
5008                 if (!r_refdef.viewcache.entityvisible[i])
5009                         continue;
5010                 ent = r_refdef.scene.entities[i];
5011                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5012                         ent->model->DrawAddWaterPlanes(ent);
5013         }
5014 }
5015
5016 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5017 {
5018         if (r_hdr_irisadaptation.integer)
5019         {
5020                 vec3_t ambient;
5021                 vec3_t diffuse;
5022                 vec3_t diffusenormal;
5023                 vec_t brightness;
5024                 vec_t goal;
5025                 vec_t current;
5026                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5027                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5028                 brightness = max(0.0000001f, brightness);
5029                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5030                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5031                 current = r_hdr_irisadaptation_value.value;
5032                 if (current < goal)
5033                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5034                 else if (current > goal)
5035                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5036                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5037                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5038         }
5039         else if (r_hdr_irisadaptation_value.value != 1.0f)
5040                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5041 }
5042
5043 static void R_View_SetFrustum(const int *scissor)
5044 {
5045         int i;
5046         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5047         vec3_t forward, left, up, origin, v;
5048
5049         if(scissor)
5050         {
5051                 // flipped x coordinates (because x points left here)
5052                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5053                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5054
5055                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5056                 switch(vid.renderpath)
5057                 {
5058                         case RENDERPATH_D3D9:
5059                         case RENDERPATH_D3D10:
5060                         case RENDERPATH_D3D11:
5061                                 // non-flipped y coordinates
5062                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5063                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5064                                 break;
5065                         case RENDERPATH_SOFT:
5066                         case RENDERPATH_GL11:
5067                         case RENDERPATH_GL13:
5068                         case RENDERPATH_GL20:
5069                         case RENDERPATH_GLES1:
5070                         case RENDERPATH_GLES2:
5071                                 // non-flipped y coordinates
5072                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5073                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5074                                 break;
5075                 }
5076         }
5077
5078         // we can't trust r_refdef.view.forward and friends in reflected scenes
5079         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5080
5081 #if 0
5082         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5083         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5084         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5085         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5086         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5087         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5088         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5089         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5090         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5091         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5092         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5093         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5094 #endif
5095
5096 #if 0
5097         zNear = r_refdef.nearclip;
5098         nudge = 1.0 - 1.0 / (1<<23);
5099         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5100         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5101         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5102         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5103         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5104         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5105         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5106         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5107 #endif
5108
5109
5110
5111 #if 0
5112         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5113         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5114         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5115         r_refdef.view.frustum[0].dist = m[15] - m[12];
5116
5117         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5118         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5119         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5120         r_refdef.view.frustum[1].dist = m[15] + m[12];
5121
5122         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5123         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5124         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5125         r_refdef.view.frustum[2].dist = m[15] - m[13];
5126
5127         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5128         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5129         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5130         r_refdef.view.frustum[3].dist = m[15] + m[13];
5131
5132         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5133         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5134         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5135         r_refdef.view.frustum[4].dist = m[15] - m[14];
5136
5137         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5138         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5139         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5140         r_refdef.view.frustum[5].dist = m[15] + m[14];
5141 #endif
5142
5143         if (r_refdef.view.useperspective)
5144         {
5145                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5146                 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]);
5147                 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]);
5148                 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]);
5149                 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]);
5150
5151                 // then the normals from the corners relative to origin
5152                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5153                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5154                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5155                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5156
5157                 // in a NORMAL view, forward cross left == up
5158                 // in a REFLECTED view, forward cross left == down
5159                 // so our cross products above need to be adjusted for a left handed coordinate system
5160                 CrossProduct(forward, left, v);
5161                 if(DotProduct(v, up) < 0)
5162                 {
5163                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5164                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5165                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5166                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5167                 }
5168
5169                 // Leaving those out was a mistake, those were in the old code, and they
5170                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5171                 // I couldn't reproduce it after adding those normalizations. --blub
5172                 VectorNormalize(r_refdef.view.frustum[0].normal);
5173                 VectorNormalize(r_refdef.view.frustum[1].normal);
5174                 VectorNormalize(r_refdef.view.frustum[2].normal);
5175                 VectorNormalize(r_refdef.view.frustum[3].normal);
5176
5177                 // make the corners absolute
5178                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5179                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5180                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5181                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5182
5183                 // one more normal
5184                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5185
5186                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5187                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5188                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5189                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5190                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5191         }
5192         else
5193         {
5194                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5195                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5196                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5197                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5198                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5199                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5200                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5201                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5202                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5203                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5204         }
5205         r_refdef.view.numfrustumplanes = 5;
5206
5207         if (r_refdef.view.useclipplane)
5208         {
5209                 r_refdef.view.numfrustumplanes = 6;
5210                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5211         }
5212
5213         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5214                 PlaneClassify(r_refdef.view.frustum + i);
5215
5216         // LordHavoc: note to all quake engine coders, Quake had a special case
5217         // for 90 degrees which assumed a square view (wrong), so I removed it,
5218         // Quake2 has it disabled as well.
5219
5220         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5221         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5222         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5223         //PlaneClassify(&frustum[0]);
5224
5225         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5226         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5227         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5228         //PlaneClassify(&frustum[1]);
5229
5230         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5231         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5232         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5233         //PlaneClassify(&frustum[2]);
5234
5235         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5236         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5237         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5238         //PlaneClassify(&frustum[3]);
5239
5240         // nearclip plane
5241         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5242         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5243         //PlaneClassify(&frustum[4]);
5244 }
5245
5246 void R_View_UpdateWithScissor(const int *myscissor)
5247 {
5248         R_Main_ResizeViewCache();
5249         R_View_SetFrustum(myscissor);
5250         R_View_WorldVisibility(r_refdef.view.useclipplane);
5251         R_View_UpdateEntityVisible();
5252         R_View_UpdateEntityLighting();
5253 }
5254
5255 void R_View_Update(void)
5256 {
5257         R_Main_ResizeViewCache();
5258         R_View_SetFrustum(NULL);
5259         R_View_WorldVisibility(r_refdef.view.useclipplane);
5260         R_View_UpdateEntityVisible();
5261         R_View_UpdateEntityLighting();
5262 }
5263
5264 float viewscalefpsadjusted = 1.0f;
5265
5266 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5267 {
5268         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5269         scale = bound(0.03125f, scale, 1.0f);
5270         *outwidth = (int)ceil(width * scale);
5271         *outheight = (int)ceil(height * scale);
5272 }
5273
5274 void R_Mesh_SetMainRenderTargets(void)
5275 {
5276         if (r_bloomstate.fbo_framebuffer)
5277                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5278         else
5279                 R_Mesh_ResetRenderTargets();
5280 }
5281
5282 void R_SetupView(qboolean allowwaterclippingplane)
5283 {
5284         const float *customclipplane = NULL;
5285         float plane[4];
5286         int scaledwidth, scaledheight;
5287         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5288         {
5289                 // LordHavoc: couldn't figure out how to make this approach the
5290                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5291                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5292                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5293                         dist = r_refdef.view.clipplane.dist;
5294                 plane[0] = r_refdef.view.clipplane.normal[0];
5295                 plane[1] = r_refdef.view.clipplane.normal[1];
5296                 plane[2] = r_refdef.view.clipplane.normal[2];
5297                 plane[3] = -dist;
5298                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5299         }
5300
5301         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5302         if (!r_refdef.view.useperspective)
5303                 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);
5304         else if (vid.stencil && r_useinfinitefarclip.integer)
5305                 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);
5306         else
5307                 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);
5308         R_Mesh_SetMainRenderTargets();
5309         R_SetViewport(&r_refdef.view.viewport);
5310         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5311         {
5312                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5313                 float screenplane[4];
5314                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5315                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5316                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5317                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5318                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5319         }
5320 }
5321
5322 void R_EntityMatrix(const matrix4x4_t *matrix)
5323 {
5324         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5325         {
5326                 gl_modelmatrixchanged = false;
5327                 gl_modelmatrix = *matrix;
5328                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5329                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5330                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5331                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5332                 CHECKGLERROR
5333                 switch(vid.renderpath)
5334                 {
5335                 case RENDERPATH_D3D9:
5336 #ifdef SUPPORTD3D
5337                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5338                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5339 #endif
5340                         break;
5341                 case RENDERPATH_D3D10:
5342                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5343                         break;
5344                 case RENDERPATH_D3D11:
5345                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5346                         break;
5347                 case RENDERPATH_GL11:
5348                 case RENDERPATH_GL13:
5349                 case RENDERPATH_GLES1:
5350                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5351                         break;
5352                 case RENDERPATH_SOFT:
5353                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5354                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5355                         break;
5356                 case RENDERPATH_GL20:
5357                 case RENDERPATH_GLES2:
5358                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5359                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5360                         break;
5361                 }
5362         }
5363 }
5364
5365 void R_ResetViewRendering2D(void)
5366 {
5367         r_viewport_t viewport;
5368         DrawQ_Finish();
5369
5370         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5371         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);
5372         R_Mesh_ResetRenderTargets();
5373         R_SetViewport(&viewport);
5374         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5375         GL_Color(1, 1, 1, 1);
5376         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5377         GL_BlendFunc(GL_ONE, GL_ZERO);
5378         GL_ScissorTest(false);
5379         GL_DepthMask(false);
5380         GL_DepthRange(0, 1);
5381         GL_DepthTest(false);
5382         GL_DepthFunc(GL_LEQUAL);
5383         R_EntityMatrix(&identitymatrix);
5384         R_Mesh_ResetTextureState();
5385         GL_PolygonOffset(0, 0);
5386         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5387         switch(vid.renderpath)
5388         {
5389         case RENDERPATH_GL11:
5390         case RENDERPATH_GL13:
5391         case RENDERPATH_GL20:
5392         case RENDERPATH_GLES1:
5393         case RENDERPATH_GLES2:
5394                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5395                 break;
5396         case RENDERPATH_D3D9:
5397         case RENDERPATH_D3D10:
5398         case RENDERPATH_D3D11:
5399         case RENDERPATH_SOFT:
5400                 break;
5401         }
5402         GL_CullFace(GL_NONE);
5403 }
5404
5405 void R_ResetViewRendering3D(void)
5406 {
5407         DrawQ_Finish();
5408
5409         R_SetupView(true);
5410         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5411         GL_Color(1, 1, 1, 1);
5412         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5413         GL_BlendFunc(GL_ONE, GL_ZERO);
5414         GL_ScissorTest(true);
5415         GL_DepthMask(true);
5416         GL_DepthRange(0, 1);
5417         GL_DepthTest(true);
5418         GL_DepthFunc(GL_LEQUAL);
5419         R_EntityMatrix(&identitymatrix);
5420         R_Mesh_ResetTextureState();
5421         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5422         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5423         switch(vid.renderpath)
5424         {
5425         case RENDERPATH_GL11:
5426         case RENDERPATH_GL13:
5427         case RENDERPATH_GL20:
5428         case RENDERPATH_GLES1:
5429         case RENDERPATH_GLES2:
5430                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5431                 break;
5432         case RENDERPATH_D3D9:
5433         case RENDERPATH_D3D10:
5434         case RENDERPATH_D3D11:
5435         case RENDERPATH_SOFT:
5436                 break;
5437         }
5438         GL_CullFace(r_refdef.view.cullface_back);
5439 }
5440
5441 /*
5442 ================
5443 R_RenderView_UpdateViewVectors
5444 ================
5445 */
5446 static void R_RenderView_UpdateViewVectors(void)
5447 {
5448         // break apart the view matrix into vectors for various purposes
5449         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5450         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5451         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5452         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5453         // make an inverted copy of the view matrix for tracking sprites
5454         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5455 }
5456
5457 void R_RenderScene(void);
5458 void R_RenderWaterPlanes(void);
5459
5460 static void R_Water_StartFrame(void)
5461 {
5462         int i;
5463         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5464         r_waterstate_waterplane_t *p;
5465
5466         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5467                 return;
5468
5469         switch(vid.renderpath)
5470         {
5471         case RENDERPATH_GL20:
5472         case RENDERPATH_D3D9:
5473         case RENDERPATH_D3D10:
5474         case RENDERPATH_D3D11:
5475         case RENDERPATH_SOFT:
5476         case RENDERPATH_GLES2:
5477                 break;
5478         case RENDERPATH_GL11:
5479         case RENDERPATH_GL13:
5480         case RENDERPATH_GLES1:
5481                 return;
5482         }
5483
5484         // set waterwidth and waterheight to the water resolution that will be
5485         // used (often less than the screen resolution for faster rendering)
5486         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5487
5488         // calculate desired texture sizes
5489         // can't use water if the card does not support the texture size
5490         if (!r_water.integer || r_showsurfaces.integer)
5491                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5492         else if (vid.support.arb_texture_non_power_of_two)
5493         {
5494                 texturewidth = waterwidth;
5495                 textureheight = waterheight;
5496                 camerawidth = waterwidth;
5497                 cameraheight = waterheight;
5498         }
5499         else
5500         {
5501                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5502                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5503                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5504                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5505         }
5506
5507         // allocate textures as needed
5508         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5509         {
5510                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5511                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5512                 {
5513                         if (p->texture_refraction)
5514                                 R_FreeTexture(p->texture_refraction);
5515                         p->texture_refraction = NULL;
5516                         if (p->texture_reflection)
5517                                 R_FreeTexture(p->texture_reflection);
5518                         p->texture_reflection = NULL;
5519                         if (p->texture_camera)
5520                                 R_FreeTexture(p->texture_camera);
5521                         p->texture_camera = NULL;
5522                 }
5523                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5524                 r_waterstate.texturewidth = texturewidth;
5525                 r_waterstate.textureheight = textureheight;
5526                 r_waterstate.camerawidth = camerawidth;
5527                 r_waterstate.cameraheight = cameraheight;
5528         }
5529
5530         if (r_waterstate.texturewidth)
5531         {
5532                 int scaledwidth, scaledheight;
5533
5534                 r_waterstate.enabled = true;
5535
5536                 // when doing a reduced render (HDR) we want to use a smaller area
5537                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5538                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5539                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5540
5541                 // set up variables that will be used in shader setup
5542                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5543                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5544                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5545                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5546         }
5547
5548         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5549         r_waterstate.numwaterplanes = 0;
5550 }
5551
5552 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5553 {
5554         int triangleindex, planeindex;
5555         const int *e;
5556         vec3_t vert[3];
5557         vec3_t normal;
5558         vec3_t center;
5559         mplane_t plane;
5560         r_waterstate_waterplane_t *p;
5561         texture_t *t = R_GetCurrentTexture(surface->texture);
5562
5563         // just use the first triangle with a valid normal for any decisions
5564         VectorClear(normal);
5565         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5566         {
5567                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5568                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5569                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5570                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5571                 if (VectorLength2(normal) >= 0.001)
5572                         break;
5573         }
5574
5575         VectorCopy(normal, plane.normal);
5576         VectorNormalize(plane.normal);
5577         plane.dist = DotProduct(vert[0], plane.normal);
5578         PlaneClassify(&plane);
5579         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5580         {
5581                 // skip backfaces (except if nocullface is set)
5582                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5583                         return;
5584                 VectorNegate(plane.normal, plane.normal);
5585                 plane.dist *= -1;
5586                 PlaneClassify(&plane);
5587         }
5588
5589
5590         // find a matching plane if there is one
5591         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5592                 if(p->camera_entity == t->camera_entity)
5593                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5594                                 break;
5595         if (planeindex >= r_waterstate.maxwaterplanes)
5596                 return; // nothing we can do, out of planes
5597
5598         // if this triangle does not fit any known plane rendered this frame, add one
5599         if (planeindex >= r_waterstate.numwaterplanes)
5600         {
5601                 // store the new plane
5602                 r_waterstate.numwaterplanes++;
5603                 p->plane = plane;
5604                 // clear materialflags and pvs
5605                 p->materialflags = 0;
5606                 p->pvsvalid = false;
5607                 p->camera_entity = t->camera_entity;
5608                 VectorCopy(surface->mins, p->mins);
5609                 VectorCopy(surface->maxs, p->maxs);
5610         }
5611         else
5612         {
5613                 // merge mins/maxs
5614                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5615                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5616                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5617                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5618                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5619                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5620         }
5621         // merge this surface's materialflags into the waterplane
5622         p->materialflags |= t->currentmaterialflags;
5623         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5624         {
5625                 // merge this surface's PVS into the waterplane
5626                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5627                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5628                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5629                 {
5630                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5631                         p->pvsvalid = true;
5632                 }
5633         }
5634 }
5635
5636 extern cvar_t r_drawparticles;
5637 extern cvar_t r_drawdecals;
5638
5639 static void R_Water_ProcessPlanes(void)
5640 {
5641         int myscissor[4];
5642         r_refdef_view_t originalview;
5643         r_refdef_view_t myview;
5644         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5645         r_waterstate_waterplane_t *p;
5646         vec3_t visorigin;
5647
5648         originalview = r_refdef.view;
5649
5650         // lowquality hack, temporarily shut down some cvars and restore afterwards
5651         qualityreduction = r_water_lowquality.integer;
5652         if (qualityreduction > 0)
5653         {
5654                 if (qualityreduction >= 1)
5655                 {
5656                         old_r_shadows = r_shadows.integer;
5657                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5658                         old_r_dlight = r_shadow_realtime_dlight.integer;
5659                         Cvar_SetValueQuick(&r_shadows, 0);
5660                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5661                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5662                 }
5663                 if (qualityreduction >= 2)
5664                 {
5665                         old_r_dynamic = r_dynamic.integer;
5666                         old_r_particles = r_drawparticles.integer;
5667                         old_r_decals = r_drawdecals.integer;
5668                         Cvar_SetValueQuick(&r_dynamic, 0);
5669                         Cvar_SetValueQuick(&r_drawparticles, 0);
5670                         Cvar_SetValueQuick(&r_drawdecals, 0);
5671                 }
5672         }
5673
5674         // make sure enough textures are allocated
5675         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5676         {
5677                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5678                 {
5679                         if (!p->texture_refraction)
5680                                 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);
5681                         if (!p->texture_refraction)
5682                                 goto error;
5683                 }
5684                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5685                 {
5686                         if (!p->texture_camera)
5687                                 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);
5688                         if (!p->texture_camera)
5689                                 goto error;
5690                 }
5691
5692                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5693                 {
5694                         if (!p->texture_reflection)
5695                                 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);
5696                         if (!p->texture_reflection)
5697                                 goto error;
5698                 }
5699         }
5700
5701         // render views
5702         r_refdef.view = originalview;
5703         r_refdef.view.showdebug = false;
5704         r_refdef.view.width = r_waterstate.waterwidth;
5705         r_refdef.view.height = r_waterstate.waterheight;
5706         r_refdef.view.useclipplane = true;
5707         myview = r_refdef.view;
5708         r_waterstate.renderingscene = true;
5709         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5710         {
5711                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5712                 {
5713                         r_refdef.view = myview;
5714                         if(r_water_scissormode.integer)
5715                         {
5716                                 R_SetupView(true);
5717                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5718                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5719                         }
5720
5721                         // render reflected scene and copy into texture
5722                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5723                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5724                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5725                         r_refdef.view.clipplane = p->plane;
5726                         // reverse the cullface settings for this render
5727                         r_refdef.view.cullface_front = GL_FRONT;
5728                         r_refdef.view.cullface_back = GL_BACK;
5729                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5730                         {
5731                                 r_refdef.view.usecustompvs = true;
5732                                 if (p->pvsvalid)
5733                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5734                                 else
5735                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5736                         }
5737
5738                         R_ResetViewRendering3D();
5739                         R_ClearScreen(r_refdef.fogenabled);
5740                         if(r_water_scissormode.integer & 2)
5741                                 R_View_UpdateWithScissor(myscissor);
5742                         else
5743                                 R_View_Update();
5744                         if(r_water_scissormode.integer & 1)
5745                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5746                         R_RenderScene();
5747
5748                         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);
5749                 }
5750
5751                 // render the normal view scene and copy into texture
5752                 // (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)
5753                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5754                 {
5755                         r_refdef.view = myview;
5756                         if(r_water_scissormode.integer)
5757                         {
5758                                 R_SetupView(true);
5759                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5760                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5761                         }
5762
5763                         r_waterstate.renderingrefraction = true;
5764
5765                         r_refdef.view.clipplane = p->plane;
5766                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5767                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5768
5769                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5770                         {
5771                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5772                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5773                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5774                                 R_RenderView_UpdateViewVectors();
5775                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5776                                 {
5777                                         r_refdef.view.usecustompvs = true;
5778                                         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);
5779                                 }
5780                         }
5781
5782                         PlaneClassify(&r_refdef.view.clipplane);
5783
5784                         R_ResetViewRendering3D();
5785                         R_ClearScreen(r_refdef.fogenabled);
5786                         if(r_water_scissormode.integer & 2)
5787                                 R_View_UpdateWithScissor(myscissor);
5788                         else
5789                                 R_View_Update();
5790                         if(r_water_scissormode.integer & 1)
5791                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5792                         R_RenderScene();
5793
5794                         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);
5795                         r_waterstate.renderingrefraction = false;
5796                 }
5797                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5798                 {
5799                         r_refdef.view = myview;
5800
5801                         r_refdef.view.clipplane = p->plane;
5802                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5803                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5804
5805                         r_refdef.view.width = r_waterstate.camerawidth;
5806                         r_refdef.view.height = r_waterstate.cameraheight;
5807                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5808                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5809
5810                         if(p->camera_entity)
5811                         {
5812                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5813                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5814                         }
5815
5816                         // note: all of the view is used for displaying... so
5817                         // there is no use in scissoring
5818
5819                         // reverse the cullface settings for this render
5820                         r_refdef.view.cullface_front = GL_FRONT;
5821                         r_refdef.view.cullface_back = GL_BACK;
5822                         // also reverse the view matrix
5823                         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
5824                         R_RenderView_UpdateViewVectors();
5825                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5826                         {
5827                                 r_refdef.view.usecustompvs = true;
5828                                 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);
5829                         }
5830                         
5831                         // camera needs no clipplane
5832                         r_refdef.view.useclipplane = false;
5833
5834                         PlaneClassify(&r_refdef.view.clipplane);
5835
5836                         R_ResetViewRendering3D();
5837                         R_ClearScreen(r_refdef.fogenabled);
5838                         R_View_Update();
5839                         R_RenderScene();
5840
5841                         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);
5842                         r_waterstate.renderingrefraction = false;
5843                 }
5844
5845         }
5846         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5847         r_waterstate.renderingscene = false;
5848         r_refdef.view = originalview;
5849         R_ResetViewRendering3D();
5850         R_ClearScreen(r_refdef.fogenabled);
5851         R_View_Update();
5852         goto finish;
5853 error:
5854         r_refdef.view = originalview;
5855         r_waterstate.renderingscene = false;
5856         Cvar_SetValueQuick(&r_water, 0);
5857         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5858 finish:
5859         // lowquality hack, restore cvars
5860         if (qualityreduction > 0)
5861         {
5862                 if (qualityreduction >= 1)
5863                 {
5864                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5865                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5866                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5867                 }
5868                 if (qualityreduction >= 2)
5869                 {
5870                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5871                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5872                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5873                 }
5874         }
5875 }
5876
5877 void R_Bloom_StartFrame(void)
5878 {
5879         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5880         int viewwidth, viewheight;
5881         textype_t textype;
5882
5883         if (r_viewscale_fpsscaling.integer)
5884         {
5885                 double actualframetime;
5886                 double targetframetime;
5887                 double adjust;
5888                 actualframetime = r_refdef.lastdrawscreentime;
5889                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5890                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5891                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5892                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5893                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5894                 viewscalefpsadjusted += adjust;
5895                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5896         }
5897         else
5898                 viewscalefpsadjusted = 1.0f;
5899
5900         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5901
5902         switch(vid.renderpath)
5903         {
5904         case RENDERPATH_GL20:
5905         case RENDERPATH_D3D9:
5906         case RENDERPATH_D3D10:
5907         case RENDERPATH_D3D11:
5908         case RENDERPATH_SOFT:
5909         case RENDERPATH_GLES2:
5910                 break;
5911         case RENDERPATH_GL11:
5912         case RENDERPATH_GL13:
5913         case RENDERPATH_GLES1:
5914                 return;
5915         }
5916
5917         // set bloomwidth and bloomheight to the bloom resolution that will be
5918         // used (often less than the screen resolution for faster rendering)
5919         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5920         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5921         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5922         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5923         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5924
5925         // calculate desired texture sizes
5926         if (vid.support.arb_texture_non_power_of_two)
5927         {
5928                 screentexturewidth = vid.width;
5929                 screentextureheight = vid.height;
5930                 bloomtexturewidth = r_bloomstate.bloomwidth;
5931                 bloomtextureheight = r_bloomstate.bloomheight;
5932         }
5933         else
5934         {
5935                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5936                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5937                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5938                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5939         }
5940
5941         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))
5942         {
5943                 Cvar_SetValueQuick(&r_hdr, 0);
5944                 Cvar_SetValueQuick(&r_bloom, 0);
5945                 Cvar_SetValueQuick(&r_motionblur, 0);
5946                 Cvar_SetValueQuick(&r_damageblur, 0);
5947         }
5948
5949         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)
5950                 screentexturewidth = screentextureheight = 0;
5951         if (!r_hdr.integer && !r_bloom.integer)
5952                 bloomtexturewidth = bloomtextureheight = 0;
5953
5954         textype = TEXTYPE_COLORBUFFER;
5955         switch (vid.renderpath)
5956         {
5957         case RENDERPATH_GL20:
5958         case RENDERPATH_GLES2:
5959                 if (vid.support.ext_framebuffer_object)
5960                 {
5961                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5962                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5963                 }
5964                 break;
5965         case RENDERPATH_GL11:
5966         case RENDERPATH_GL13:
5967         case RENDERPATH_GLES1:
5968         case RENDERPATH_D3D9:
5969         case RENDERPATH_D3D10:
5970         case RENDERPATH_D3D11:
5971         case RENDERPATH_SOFT:
5972                 break;
5973         }
5974
5975         // allocate textures as needed
5976         if (r_bloomstate.screentexturewidth != screentexturewidth
5977          || r_bloomstate.screentextureheight != screentextureheight
5978          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5979          || r_bloomstate.bloomtextureheight != bloomtextureheight
5980          || r_bloomstate.texturetype != textype
5981          || r_bloomstate.viewfbo != r_viewfbo.integer)
5982         {
5983                 if (r_bloomstate.texture_bloom)
5984                         R_FreeTexture(r_bloomstate.texture_bloom);
5985                 r_bloomstate.texture_bloom = NULL;
5986                 if (r_bloomstate.texture_screen)
5987                         R_FreeTexture(r_bloomstate.texture_screen);
5988                 r_bloomstate.texture_screen = NULL;
5989                 if (r_bloomstate.fbo_framebuffer)
5990                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5991                 r_bloomstate.fbo_framebuffer = 0;
5992                 if (r_bloomstate.texture_framebuffercolor)
5993                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5994                 r_bloomstate.texture_framebuffercolor = NULL;
5995                 if (r_bloomstate.texture_framebufferdepth)
5996                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5997                 r_bloomstate.texture_framebufferdepth = NULL;
5998                 r_bloomstate.screentexturewidth = screentexturewidth;
5999                 r_bloomstate.screentextureheight = screentextureheight;
6000                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6001                         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);
6002                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6003                 {
6004                         // FIXME: choose depth bits based on a cvar
6005                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6006                         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);
6007                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6008                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6009                         // render depth into one texture and normalmap into the other
6010                         if (qglDrawBuffer)
6011                         {
6012                                 int status;
6013                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6014                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6015                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6016                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6017                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6018                         }
6019                 }
6020                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6021                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6022                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6023                         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);
6024                 r_bloomstate.viewfbo = r_viewfbo.integer;
6025                 r_bloomstate.texturetype = textype;
6026         }
6027
6028         // when doing a reduced render (HDR) we want to use a smaller area
6029         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6030         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6031         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6032         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6033         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6034
6035         // set up a texcoord array for the full resolution screen image
6036         // (we have to keep this around to copy back during final render)
6037         r_bloomstate.screentexcoord2f[0] = 0;
6038         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6039         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6040         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6041         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6042         r_bloomstate.screentexcoord2f[5] = 0;
6043         r_bloomstate.screentexcoord2f[6] = 0;
6044         r_bloomstate.screentexcoord2f[7] = 0;
6045
6046         // set up a texcoord array for the reduced resolution bloom image
6047         // (which will be additive blended over the screen image)
6048         r_bloomstate.bloomtexcoord2f[0] = 0;
6049         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6050         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6051         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6052         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6053         r_bloomstate.bloomtexcoord2f[5] = 0;
6054         r_bloomstate.bloomtexcoord2f[6] = 0;
6055         r_bloomstate.bloomtexcoord2f[7] = 0;
6056
6057         switch(vid.renderpath)
6058         {
6059         case RENDERPATH_GL11:
6060         case RENDERPATH_GL13:
6061         case RENDERPATH_GL20:
6062         case RENDERPATH_SOFT:
6063         case RENDERPATH_GLES1:
6064         case RENDERPATH_GLES2:
6065                 break;
6066         case RENDERPATH_D3D9:
6067         case RENDERPATH_D3D10:
6068         case RENDERPATH_D3D11:
6069                 {
6070                         int i;
6071                         for (i = 0;i < 4;i++)
6072                         {
6073                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6074                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6075                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6076                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6077                         }
6078                 }
6079                 break;
6080         }
6081
6082         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6083         {
6084                 r_bloomstate.enabled = true;
6085                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6086         }
6087
6088         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);
6089
6090         if (r_bloomstate.fbo_framebuffer)
6091                 r_refdef.view.clear = true;
6092 }
6093
6094 void R_Bloom_CopyBloomTexture(float colorscale)
6095 {
6096         r_refdef.stats.bloom++;
6097
6098         // scale down screen texture to the bloom texture size
6099         CHECKGLERROR
6100         R_Mesh_SetMainRenderTargets();
6101         R_SetViewport(&r_bloomstate.viewport);
6102         GL_BlendFunc(GL_ONE, GL_ZERO);
6103         GL_Color(colorscale, colorscale, colorscale, 1);
6104         // 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...
6105         switch(vid.renderpath)
6106         {
6107         case RENDERPATH_GL11:
6108         case RENDERPATH_GL13:
6109         case RENDERPATH_GL20:
6110         case RENDERPATH_GLES1:
6111         case RENDERPATH_GLES2:
6112         case RENDERPATH_SOFT:
6113                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6114                 break;
6115         case RENDERPATH_D3D9:
6116         case RENDERPATH_D3D10:
6117         case RENDERPATH_D3D11:
6118                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6119                 break;
6120         }
6121         // TODO: do boxfilter scale-down in shader?
6122         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6123         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6124         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6125
6126         // we now have a bloom image in the framebuffer
6127         // copy it into the bloom image texture for later processing
6128         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);
6129         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6130 }
6131
6132 void R_Bloom_CopyHDRTexture(void)
6133 {
6134         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);
6135         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6136 }
6137
6138 void R_Bloom_MakeTexture(void)
6139 {
6140         int x, range, dir;
6141         float xoffset, yoffset, r, brighten;
6142
6143         r_refdef.stats.bloom++;
6144
6145         R_ResetViewRendering2D();
6146
6147         // we have a bloom image in the framebuffer
6148         CHECKGLERROR
6149         R_SetViewport(&r_bloomstate.viewport);
6150
6151         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6152         {
6153                 x *= 2;
6154                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6155                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6156                 GL_Color(r,r,r,1);
6157                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6158                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6159                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6160                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6161
6162                 // copy the vertically blurred bloom view to a texture
6163                 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);
6164                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6165         }
6166
6167         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6168         brighten = r_bloom_brighten.value;
6169         if (r_bloomstate.hdr)
6170                 brighten *= r_hdr_range.value;
6171         brighten = sqrt(brighten);
6172         if(range >= 1)
6173                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6174         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6175
6176         for (dir = 0;dir < 2;dir++)
6177         {
6178                 // blend on at multiple vertical offsets to achieve a vertical blur
6179                 // TODO: do offset blends using GLSL
6180                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6181                 GL_BlendFunc(GL_ONE, GL_ZERO);
6182                 for (x = -range;x <= range;x++)
6183                 {
6184                         if (!dir){xoffset = 0;yoffset = x;}
6185                         else {xoffset = x;yoffset = 0;}
6186                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6187                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6188                         // compute a texcoord array with the specified x and y offset
6189                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6190                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6191                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6192                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6193                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6194                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6195                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6196                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6197                         // this r value looks like a 'dot' particle, fading sharply to
6198                         // black at the edges
6199                         // (probably not realistic but looks good enough)
6200                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6201                         //r = brighten/(range*2+1);
6202                         r = brighten / (range * 2 + 1);
6203                         if(range >= 1)
6204                                 r *= (1 - x*x/(float)(range*range));
6205                         GL_Color(r, r, r, 1);
6206                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6207                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6208                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6209                         GL_BlendFunc(GL_ONE, GL_ONE);
6210                 }
6211
6212                 // copy the vertically blurred bloom view to a texture
6213                 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);
6214                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6215         }
6216 }
6217
6218 void R_HDR_RenderBloomTexture(void)
6219 {
6220         int oldwidth, oldheight;
6221         float oldcolorscale;
6222         qboolean oldwaterstate;
6223
6224         oldwaterstate = r_waterstate.enabled;
6225         oldcolorscale = r_refdef.view.colorscale;
6226         oldwidth = r_refdef.view.width;
6227         oldheight = r_refdef.view.height;
6228         r_refdef.view.width = r_bloomstate.bloomwidth;
6229         r_refdef.view.height = r_bloomstate.bloomheight;
6230
6231         if(r_hdr.integer < 2)
6232                 r_waterstate.enabled = false;
6233
6234         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6235         // TODO: add exposure compensation features
6236         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6237
6238         r_refdef.view.showdebug = false;
6239         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6240
6241         R_ResetViewRendering3D();
6242
6243         R_ClearScreen(r_refdef.fogenabled);
6244         if (r_timereport_active)
6245                 R_TimeReport("HDRclear");
6246
6247         R_View_Update();
6248         if (r_timereport_active)
6249                 R_TimeReport("visibility");
6250
6251         // only do secondary renders with HDR if r_hdr is 2 or higher
6252         r_waterstate.numwaterplanes = 0;
6253         if (r_waterstate.enabled)
6254                 R_RenderWaterPlanes();
6255
6256         r_refdef.view.showdebug = true;
6257         R_RenderScene();
6258         r_waterstate.numwaterplanes = 0;
6259
6260         R_ResetViewRendering2D();
6261
6262         R_Bloom_CopyHDRTexture();
6263         R_Bloom_MakeTexture();
6264
6265         // restore the view settings
6266         r_waterstate.enabled = oldwaterstate;
6267         r_refdef.view.width = oldwidth;
6268         r_refdef.view.height = oldheight;
6269         r_refdef.view.colorscale = oldcolorscale;
6270
6271         R_ResetViewRendering3D();
6272
6273         R_ClearScreen(r_refdef.fogenabled);
6274         if (r_timereport_active)
6275                 R_TimeReport("viewclear");
6276 }
6277
6278 static void R_BlendView(void)
6279 {
6280         unsigned int permutation;
6281         float uservecs[4][4];
6282
6283         switch (vid.renderpath)
6284         {
6285         case RENDERPATH_GL20:
6286         case RENDERPATH_D3D9:
6287         case RENDERPATH_D3D10:
6288         case RENDERPATH_D3D11:
6289         case RENDERPATH_SOFT:
6290         case RENDERPATH_GLES2:
6291                 permutation =
6292                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6293                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6294                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6295                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6296                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6297
6298                 if (r_bloomstate.texture_screen)
6299                 {
6300                         // make sure the buffer is available
6301                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6302
6303                         R_ResetViewRendering2D();
6304                         R_Mesh_SetMainRenderTargets();
6305
6306                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6307                         {
6308                                 // declare variables
6309                                 float blur_factor, blur_mouseaccel, blur_velocity;
6310                                 static float blur_average; 
6311                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6312
6313                                 // set a goal for the factoring
6314                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6315                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6316                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6317                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6318                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6319                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6320
6321                                 // from the goal, pick an averaged value between goal and last value
6322                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6323                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6324                                 
6325                                 // enforce minimum amount of blur 
6326                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6327                                 
6328                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6329
6330                                 // calculate values into a standard alpha
6331                                 cl.motionbluralpha = 1 - exp(-
6332                                                 (
6333                                                  (r_motionblur.value * blur_factor / 80)
6334                                                  +
6335                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6336                                                 )
6337                                                 /
6338                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6339                                           );
6340                                 
6341                                 // randomization for the blur value to combat persistent ghosting
6342                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6343                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6344                                 
6345                                 // apply the blur
6346                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6347                                 {
6348                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6349                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6350                                         switch(vid.renderpath)
6351                                         {
6352                                         case RENDERPATH_GL11:
6353                                         case RENDERPATH_GL13:
6354                                         case RENDERPATH_GL20:
6355                                         case RENDERPATH_GLES1:
6356                                         case RENDERPATH_GLES2:
6357                                         case RENDERPATH_SOFT:
6358                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6359                                                 break;
6360                                         case RENDERPATH_D3D9:
6361                                         case RENDERPATH_D3D10:
6362                                         case RENDERPATH_D3D11:
6363                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6364                                                 break;
6365                                         }
6366                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6367                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6368                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6369                                 }
6370                                 
6371                                 // updates old view angles for next pass 
6372                                 VectorCopy(cl.viewangles, blur_oldangles);
6373                         }
6374
6375                         // copy view into the screen texture
6376                         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);
6377                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6378                 }
6379                 else if (!r_bloomstate.texture_bloom)
6380                 {
6381                         // we may still have to do view tint...
6382                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6383                         {
6384                                 // apply a color tint to the whole view
6385                                 R_ResetViewRendering2D();
6386                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6387                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6388                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6389                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6390                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6391                         }
6392                         break; // no screen processing, no bloom, skip it
6393                 }
6394
6395                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6396                 {
6397                         // render simple bloom effect
6398                         // copy the screen and shrink it and darken it for the bloom process
6399                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6400                         // make the bloom texture
6401                         R_Bloom_MakeTexture();
6402                 }
6403
6404 #if _MSC_VER >= 1400
6405 #define sscanf sscanf_s
6406 #endif
6407                 memset(uservecs, 0, sizeof(uservecs));
6408                 if (r_glsl_postprocess_uservec1_enable.integer)
6409                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6410                 if (r_glsl_postprocess_uservec2_enable.integer)
6411                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6412                 if (r_glsl_postprocess_uservec3_enable.integer)
6413                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6414                 if (r_glsl_postprocess_uservec4_enable.integer)
6415                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6416
6417                 R_ResetViewRendering2D();
6418                 GL_Color(1, 1, 1, 1);
6419                 GL_BlendFunc(GL_ONE, GL_ZERO);
6420
6421                 switch(vid.renderpath)
6422                 {
6423                 case RENDERPATH_GL20:
6424                 case RENDERPATH_GLES2:
6425                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6426                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6427                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6428                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6429                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6430                         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]);
6431                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6432                         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]);
6433                         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]);
6434                         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]);
6435                         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]);
6436                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6437                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6438                         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);
6439                         break;
6440                 case RENDERPATH_D3D9:
6441 #ifdef SUPPORTD3D
6442                         // 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...
6443                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6444                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6445                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6446                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6447                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6448                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6449                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6450                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6451                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6452                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6453                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6454                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6455                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6456                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6457 #endif
6458                         break;
6459                 case RENDERPATH_D3D10:
6460                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6461                         break;
6462                 case RENDERPATH_D3D11:
6463                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6464                         break;
6465                 case RENDERPATH_SOFT:
6466                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6467                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6468                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6469                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6470                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6471                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6472                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6473                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6474                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6475                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6476                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6477                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6478                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6479                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6480                         break;
6481                 default:
6482                         break;
6483                 }
6484                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6485                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6486                 break;
6487         case RENDERPATH_GL11:
6488         case RENDERPATH_GL13:
6489         case RENDERPATH_GLES1:
6490                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6491                 {
6492                         // apply a color tint to the whole view
6493                         R_ResetViewRendering2D();
6494                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6495                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6496                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6497                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6498                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6499                 }
6500                 break;
6501         }
6502 }
6503
6504 matrix4x4_t r_waterscrollmatrix;
6505
6506 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6507 {
6508         if (r_refdef.fog_density)
6509         {
6510                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6511                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6512                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6513
6514                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6515                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6516                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6517                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6518
6519                 {
6520                         vec3_t fogvec;
6521                         VectorCopy(r_refdef.fogcolor, fogvec);
6522                         //   color.rgb *= ContrastBoost * SceneBrightness;
6523                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6524                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6525                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6526                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6527                 }
6528         }
6529 }
6530
6531 void R_UpdateVariables(void)
6532 {
6533         R_Textures_Frame();
6534
6535         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6536
6537         r_refdef.farclip = r_farclip_base.value;
6538         if (r_refdef.scene.worldmodel)
6539                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6540         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6541
6542         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6543                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6544         r_refdef.polygonfactor = 0;
6545         r_refdef.polygonoffset = 0;
6546         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6547         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6548
6549         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6550         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6551         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6552         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6553         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6554         if (FAKELIGHT_ENABLED)
6555         {
6556                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6557         }
6558         if (r_showsurfaces.integer)
6559         {
6560                 r_refdef.scene.rtworld = false;
6561                 r_refdef.scene.rtworldshadows = false;
6562                 r_refdef.scene.rtdlight = false;
6563                 r_refdef.scene.rtdlightshadows = false;
6564                 r_refdef.lightmapintensity = 0;
6565         }
6566
6567         if (gamemode == GAME_NEHAHRA)
6568         {
6569                 if (gl_fogenable.integer)
6570                 {
6571                         r_refdef.oldgl_fogenable = true;
6572                         r_refdef.fog_density = gl_fogdensity.value;
6573                         r_refdef.fog_red = gl_fogred.value;
6574                         r_refdef.fog_green = gl_foggreen.value;
6575                         r_refdef.fog_blue = gl_fogblue.value;
6576                         r_refdef.fog_alpha = 1;
6577                         r_refdef.fog_start = 0;
6578                         r_refdef.fog_end = gl_skyclip.value;
6579                         r_refdef.fog_height = 1<<30;
6580                         r_refdef.fog_fadedepth = 128;
6581                 }
6582                 else if (r_refdef.oldgl_fogenable)
6583                 {
6584                         r_refdef.oldgl_fogenable = false;
6585                         r_refdef.fog_density = 0;
6586                         r_refdef.fog_red = 0;
6587                         r_refdef.fog_green = 0;
6588                         r_refdef.fog_blue = 0;
6589                         r_refdef.fog_alpha = 0;
6590                         r_refdef.fog_start = 0;
6591                         r_refdef.fog_end = 0;
6592                         r_refdef.fog_height = 1<<30;
6593                         r_refdef.fog_fadedepth = 128;
6594                 }
6595         }
6596
6597         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6598         r_refdef.fog_start = max(0, r_refdef.fog_start);
6599         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6600
6601         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6602
6603         if (r_refdef.fog_density && r_drawfog.integer)
6604         {
6605                 r_refdef.fogenabled = true;
6606                 // this is the point where the fog reaches 0.9986 alpha, which we
6607                 // consider a good enough cutoff point for the texture
6608                 // (0.9986 * 256 == 255.6)
6609                 if (r_fog_exp2.integer)
6610                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6611                 else
6612                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6613                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6614                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6615                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6616                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6617                         R_BuildFogHeightTexture();
6618                 // fog color was already set
6619                 // update the fog texture
6620                 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)
6621                         R_BuildFogTexture();
6622                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6623                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6624         }
6625         else
6626                 r_refdef.fogenabled = false;
6627
6628         switch(vid.renderpath)
6629         {
6630         case RENDERPATH_GL20:
6631         case RENDERPATH_D3D9:
6632         case RENDERPATH_D3D10:
6633         case RENDERPATH_D3D11:
6634         case RENDERPATH_SOFT:
6635         case RENDERPATH_GLES2:
6636                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6637                 {
6638                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6639                         {
6640                                 // build GLSL gamma texture
6641 #define RAMPWIDTH 256
6642                                 unsigned short ramp[RAMPWIDTH * 3];
6643                                 unsigned char rampbgr[RAMPWIDTH][4];
6644                                 int i;
6645
6646                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6647
6648                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6649                                 for(i = 0; i < RAMPWIDTH; ++i)
6650                                 {
6651                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6652                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6653                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6654                                         rampbgr[i][3] = 0;
6655                                 }
6656                                 if (r_texture_gammaramps)
6657                                 {
6658                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6659                                 }
6660                                 else
6661                                 {
6662                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6663                                 }
6664                         }
6665                 }
6666                 else
6667                 {
6668                         // remove GLSL gamma texture
6669                 }
6670                 break;
6671         case RENDERPATH_GL11:
6672         case RENDERPATH_GL13:
6673         case RENDERPATH_GLES1:
6674                 break;
6675         }
6676 }
6677
6678 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6679 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6680 /*
6681 ================
6682 R_SelectScene
6683 ================
6684 */
6685 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6686         if( scenetype != r_currentscenetype ) {
6687                 // store the old scenetype
6688                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6689                 r_currentscenetype = scenetype;
6690                 // move in the new scene
6691                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6692         }
6693 }
6694
6695 /*
6696 ================
6697 R_GetScenePointer
6698 ================
6699 */
6700 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6701 {
6702         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6703         if( scenetype == r_currentscenetype ) {
6704                 return &r_refdef.scene;
6705         } else {
6706                 return &r_scenes_store[ scenetype ];
6707         }
6708 }
6709
6710 /*
6711 ================
6712 R_RenderView
6713 ================
6714 */
6715 int dpsoftrast_test;
6716 extern void R_Shadow_UpdateBounceGridTexture(void);
6717 extern cvar_t r_shadow_bouncegrid;
6718 void R_RenderView(void)
6719 {
6720         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6721
6722         dpsoftrast_test = r_test.integer;
6723
6724         if (r_timereport_active)
6725                 R_TimeReport("start");
6726         r_textureframe++; // used only by R_GetCurrentTexture
6727         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6728
6729         if(R_CompileShader_CheckStaticParms())
6730                 R_GLSL_Restart_f();
6731
6732         if (!r_drawentities.integer)
6733                 r_refdef.scene.numentities = 0;
6734
6735         R_AnimCache_ClearCache();
6736         R_FrameData_NewFrame();
6737
6738         /* adjust for stereo display */
6739         if(R_Stereo_Active())
6740         {
6741                 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);
6742                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6743         }
6744
6745         if (r_refdef.view.isoverlay)
6746         {
6747                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6748                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6749                 R_TimeReport("depthclear");
6750
6751                 r_refdef.view.showdebug = false;
6752
6753                 r_waterstate.enabled = false;
6754                 r_waterstate.numwaterplanes = 0;
6755
6756                 R_RenderScene();
6757
6758                 r_refdef.view.matrix = originalmatrix;
6759
6760                 CHECKGLERROR
6761                 return;
6762         }
6763
6764         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6765         {
6766                 r_refdef.view.matrix = originalmatrix;
6767                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6768         }
6769
6770         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6771
6772         R_RenderView_UpdateViewVectors();
6773
6774         R_Shadow_UpdateWorldLightSelection();
6775
6776         R_Bloom_StartFrame();
6777         R_Water_StartFrame();
6778
6779         CHECKGLERROR
6780         if (r_timereport_active)
6781                 R_TimeReport("viewsetup");
6782
6783         R_ResetViewRendering3D();
6784
6785         if (r_refdef.view.clear || r_refdef.fogenabled)
6786         {
6787                 R_ClearScreen(r_refdef.fogenabled);
6788                 if (r_timereport_active)
6789                         R_TimeReport("viewclear");
6790         }
6791         r_refdef.view.clear = true;
6792
6793         // this produces a bloom texture to be used in R_BlendView() later
6794         if (r_bloomstate.hdr)
6795         {
6796                 R_HDR_RenderBloomTexture();
6797                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6798                 r_textureframe++; // used only by R_GetCurrentTexture
6799         }
6800
6801         r_refdef.view.showdebug = true;
6802
6803         R_View_Update();
6804         if (r_timereport_active)
6805                 R_TimeReport("visibility");
6806
6807         R_Shadow_UpdateBounceGridTexture();
6808         if (r_timereport_active && r_shadow_bouncegrid.integer)
6809                 R_TimeReport("bouncegrid");
6810
6811         r_waterstate.numwaterplanes = 0;
6812         if (r_waterstate.enabled)
6813                 R_RenderWaterPlanes();
6814
6815         R_RenderScene();
6816         r_waterstate.numwaterplanes = 0;
6817
6818         R_BlendView();
6819         if (r_timereport_active)
6820                 R_TimeReport("blendview");
6821
6822         GL_Scissor(0, 0, vid.width, vid.height);
6823         GL_ScissorTest(false);
6824
6825         r_refdef.view.matrix = originalmatrix;
6826
6827         CHECKGLERROR
6828 }
6829
6830 void R_RenderWaterPlanes(void)
6831 {
6832         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6833         {
6834                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6835                 if (r_timereport_active)
6836                         R_TimeReport("waterworld");
6837         }
6838
6839         // don't let sound skip if going slow
6840         if (r_refdef.scene.extraupdate)
6841                 S_ExtraUpdate ();
6842
6843         R_DrawModelsAddWaterPlanes();
6844         if (r_timereport_active)
6845                 R_TimeReport("watermodels");
6846
6847         if (r_waterstate.numwaterplanes)
6848         {
6849                 R_Water_ProcessPlanes();
6850                 if (r_timereport_active)
6851                         R_TimeReport("waterscenes");
6852         }
6853 }
6854
6855 extern void R_DrawLightningBeams (void);
6856 extern void VM_CL_AddPolygonsToMeshQueue (void);
6857 extern void R_DrawPortals (void);
6858 extern cvar_t cl_locs_show;
6859 static void R_DrawLocs(void);
6860 static void R_DrawEntityBBoxes(void);
6861 static void R_DrawModelDecals(void);
6862 extern void R_DrawModelShadows(void);
6863 extern void R_DrawModelShadowMaps(void);
6864 extern cvar_t cl_decals_newsystem;
6865 extern qboolean r_shadow_usingdeferredprepass;
6866 void R_RenderScene(void)
6867 {
6868         qboolean shadowmapping = false;
6869
6870         if (r_timereport_active)
6871                 R_TimeReport("beginscene");
6872
6873         r_refdef.stats.renders++;
6874
6875         R_UpdateFogColor();
6876
6877         // don't let sound skip if going slow
6878         if (r_refdef.scene.extraupdate)
6879                 S_ExtraUpdate ();
6880
6881         R_MeshQueue_BeginScene();
6882
6883         R_SkyStartFrame();
6884
6885         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);
6886
6887         if (r_timereport_active)
6888                 R_TimeReport("skystartframe");
6889
6890         if (cl.csqc_vidvars.drawworld)
6891         {
6892                 // don't let sound skip if going slow
6893                 if (r_refdef.scene.extraupdate)
6894                         S_ExtraUpdate ();
6895
6896                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6897                 {
6898                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6899                         if (r_timereport_active)
6900                                 R_TimeReport("worldsky");
6901                 }
6902
6903                 if (R_DrawBrushModelsSky() && r_timereport_active)
6904                         R_TimeReport("bmodelsky");
6905
6906                 if (skyrendermasked && skyrenderlater)
6907                 {
6908                         // we have to force off the water clipping plane while rendering sky
6909                         R_SetupView(false);
6910                         R_Sky();
6911                         R_SetupView(true);
6912                         if (r_timereport_active)
6913                                 R_TimeReport("sky");
6914                 }
6915         }
6916
6917         R_AnimCache_CacheVisibleEntities();
6918         if (r_timereport_active)
6919                 R_TimeReport("animation");
6920
6921         R_Shadow_PrepareLights();
6922         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6923                 R_Shadow_PrepareModelShadows();
6924         if (r_timereport_active)
6925                 R_TimeReport("preparelights");
6926
6927         if (R_Shadow_ShadowMappingEnabled())
6928                 shadowmapping = true;
6929
6930         if (r_shadow_usingdeferredprepass)
6931                 R_Shadow_DrawPrepass();
6932
6933         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6934         {
6935                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6936                 if (r_timereport_active)
6937                         R_TimeReport("worlddepth");
6938         }
6939         if (r_depthfirst.integer >= 2)
6940         {
6941                 R_DrawModelsDepth();
6942                 if (r_timereport_active)
6943                         R_TimeReport("modeldepth");
6944         }
6945
6946         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6947         {
6948                 R_DrawModelShadowMaps();
6949                 R_ResetViewRendering3D();
6950                 // don't let sound skip if going slow
6951                 if (r_refdef.scene.extraupdate)
6952                         S_ExtraUpdate ();
6953         }
6954
6955         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6956         {
6957                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6958                 if (r_timereport_active)
6959                         R_TimeReport("world");
6960         }
6961
6962         // don't let sound skip if going slow
6963         if (r_refdef.scene.extraupdate)
6964                 S_ExtraUpdate ();
6965
6966         R_DrawModels();
6967         if (r_timereport_active)
6968                 R_TimeReport("models");
6969
6970         // don't let sound skip if going slow
6971         if (r_refdef.scene.extraupdate)
6972                 S_ExtraUpdate ();
6973
6974         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6975         {
6976                 R_DrawModelShadows();
6977                 R_ResetViewRendering3D();
6978                 // don't let sound skip if going slow
6979                 if (r_refdef.scene.extraupdate)
6980                         S_ExtraUpdate ();
6981         }
6982
6983         if (!r_shadow_usingdeferredprepass)
6984         {
6985                 R_Shadow_DrawLights();
6986                 if (r_timereport_active)
6987                         R_TimeReport("rtlights");
6988         }
6989
6990         // don't let sound skip if going slow
6991         if (r_refdef.scene.extraupdate)
6992                 S_ExtraUpdate ();
6993
6994         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6995         {
6996                 R_DrawModelShadows();
6997                 R_ResetViewRendering3D();
6998                 // don't let sound skip if going slow
6999                 if (r_refdef.scene.extraupdate)
7000                         S_ExtraUpdate ();
7001         }
7002
7003         if (cl.csqc_vidvars.drawworld)
7004         {
7005                 if (cl_decals_newsystem.integer)
7006                 {
7007                         R_DrawModelDecals();
7008                         if (r_timereport_active)
7009                                 R_TimeReport("modeldecals");
7010                 }
7011                 else
7012                 {
7013                         R_DrawDecals();
7014                         if (r_timereport_active)
7015                                 R_TimeReport("decals");
7016                 }
7017
7018                 R_DrawParticles();
7019                 if (r_timereport_active)
7020                         R_TimeReport("particles");
7021
7022                 R_DrawExplosions();
7023                 if (r_timereport_active)
7024                         R_TimeReport("explosions");
7025
7026                 R_DrawLightningBeams();
7027                 if (r_timereport_active)
7028                         R_TimeReport("lightning");
7029         }
7030
7031         VM_CL_AddPolygonsToMeshQueue();
7032
7033         if (r_refdef.view.showdebug)
7034         {
7035                 if (cl_locs_show.integer)
7036                 {
7037                         R_DrawLocs();
7038                         if (r_timereport_active)
7039                                 R_TimeReport("showlocs");
7040                 }
7041
7042                 if (r_drawportals.integer)
7043                 {
7044                         R_DrawPortals();
7045                         if (r_timereport_active)
7046                                 R_TimeReport("portals");
7047                 }
7048
7049                 if (r_showbboxes.value > 0)
7050                 {
7051                         R_DrawEntityBBoxes();
7052                         if (r_timereport_active)
7053                                 R_TimeReport("bboxes");
7054                 }
7055         }
7056
7057         if (r_transparent.integer)
7058         {
7059                 R_MeshQueue_RenderTransparent();
7060                 if (r_timereport_active)
7061                         R_TimeReport("drawtrans");
7062         }
7063
7064         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 || r_showoverdraw.value > 0))
7065         {
7066                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7067                 if (r_timereport_active)
7068                         R_TimeReport("worlddebug");
7069                 R_DrawModelsDebug();
7070                 if (r_timereport_active)
7071                         R_TimeReport("modeldebug");
7072         }
7073
7074         if (cl.csqc_vidvars.drawworld)
7075         {
7076                 R_Shadow_DrawCoronas();
7077                 if (r_timereport_active)
7078                         R_TimeReport("coronas");
7079         }
7080
7081 #if 0
7082         {
7083                 GL_DepthTest(false);
7084                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7085                 GL_Color(1, 1, 1, 1);
7086                 qglBegin(GL_POLYGON);
7087                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7088                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7089                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7090                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7091                 qglEnd();
7092                 qglBegin(GL_POLYGON);
7093                 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]);
7094                 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]);
7095                 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]);
7096                 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]);
7097                 qglEnd();
7098                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7099         }
7100 #endif
7101
7102         // don't let sound skip if going slow
7103         if (r_refdef.scene.extraupdate)
7104                 S_ExtraUpdate ();
7105
7106         R_ResetViewRendering2D();
7107 }
7108
7109 static const unsigned short bboxelements[36] =
7110 {
7111         5, 1, 3, 5, 3, 7,
7112         6, 2, 0, 6, 0, 4,
7113         7, 3, 2, 7, 2, 6,
7114         4, 0, 1, 4, 1, 5,
7115         4, 5, 7, 4, 7, 6,
7116         1, 0, 2, 1, 2, 3,
7117 };
7118
7119 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7120 {
7121         int i;
7122         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7123
7124         RSurf_ActiveWorldEntity();
7125
7126         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7127         GL_DepthMask(false);
7128         GL_DepthRange(0, 1);
7129         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7130 //      R_Mesh_ResetTextureState();
7131
7132         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7133         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7134         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7135         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7136         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7137         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7138         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7139         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7140         R_FillColors(color4f, 8, cr, cg, cb, ca);
7141         if (r_refdef.fogenabled)
7142         {
7143                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7144                 {
7145                         f1 = RSurf_FogVertex(v);
7146                         f2 = 1 - f1;
7147                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7148                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7149                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7150                 }
7151         }
7152         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7153         R_Mesh_ResetTextureState();
7154         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7155         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7156 }
7157
7158 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7159 {
7160         int i;
7161         float color[4];
7162         prvm_edict_t *edict;
7163         prvm_prog_t *prog_save = prog;
7164
7165         // this function draws bounding boxes of server entities
7166         if (!sv.active)
7167                 return;
7168
7169         GL_CullFace(GL_NONE);
7170         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7171
7172         prog = 0;
7173         SV_VM_Begin();
7174         for (i = 0;i < numsurfaces;i++)
7175         {
7176                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7177                 switch ((int)PRVM_serveredictfloat(edict, solid))
7178                 {
7179                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7180                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7181                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7182                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7183                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7184                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7185                 }
7186                 color[3] *= r_showbboxes.value;
7187                 color[3] = bound(0, color[3], 1);
7188                 GL_DepthTest(!r_showdisabledepthtest.integer);
7189                 GL_CullFace(r_refdef.view.cullface_front);
7190                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7191         }
7192         SV_VM_End();
7193         prog = prog_save;
7194 }
7195
7196 static void R_DrawEntityBBoxes(void)
7197 {
7198         int i;
7199         prvm_edict_t *edict;
7200         vec3_t center;
7201         prvm_prog_t *prog_save = prog;
7202
7203         // this function draws bounding boxes of server entities
7204         if (!sv.active)
7205                 return;
7206
7207         prog = 0;
7208         SV_VM_Begin();
7209         for (i = 0;i < prog->num_edicts;i++)
7210         {
7211                 edict = PRVM_EDICT_NUM(i);
7212                 if (edict->priv.server->free)
7213                         continue;
7214                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7215                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7216                         continue;
7217                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7218                         continue;
7219                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7220                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7221         }
7222         SV_VM_End();
7223         prog = prog_save;
7224 }
7225
7226 static const int nomodelelement3i[24] =
7227 {
7228         5, 2, 0,
7229         5, 1, 2,
7230         5, 0, 3,
7231         5, 3, 1,
7232         0, 2, 4,
7233         2, 1, 4,
7234         3, 0, 4,
7235         1, 3, 4
7236 };
7237
7238 static const unsigned short nomodelelement3s[24] =
7239 {
7240         5, 2, 0,
7241         5, 1, 2,
7242         5, 0, 3,
7243         5, 3, 1,
7244         0, 2, 4,
7245         2, 1, 4,
7246         3, 0, 4,
7247         1, 3, 4
7248 };
7249
7250 static const float nomodelvertex3f[6*3] =
7251 {
7252         -16,   0,   0,
7253          16,   0,   0,
7254           0, -16,   0,
7255           0,  16,   0,
7256           0,   0, -16,
7257           0,   0,  16
7258 };
7259
7260 static const float nomodelcolor4f[6*4] =
7261 {
7262         0.0f, 0.0f, 0.5f, 1.0f,
7263         0.0f, 0.0f, 0.5f, 1.0f,
7264         0.0f, 0.5f, 0.0f, 1.0f,
7265         0.0f, 0.5f, 0.0f, 1.0f,
7266         0.5f, 0.0f, 0.0f, 1.0f,
7267         0.5f, 0.0f, 0.0f, 1.0f
7268 };
7269
7270 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7271 {
7272         int i;
7273         float f1, f2, *c;
7274         float color4f[6*4];
7275
7276         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);
7277
7278         // this is only called once per entity so numsurfaces is always 1, and
7279         // surfacelist is always {0}, so this code does not handle batches
7280
7281         if (rsurface.ent_flags & RENDER_ADDITIVE)
7282         {
7283                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7284                 GL_DepthMask(false);
7285         }
7286         else if (rsurface.colormod[3] < 1)
7287         {
7288                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7289                 GL_DepthMask(false);
7290         }
7291         else
7292         {
7293                 GL_BlendFunc(GL_ONE, GL_ZERO);
7294                 GL_DepthMask(true);
7295         }
7296         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7297         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7298         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7299         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7300         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7301         for (i = 0, c = color4f;i < 6;i++, c += 4)
7302         {
7303                 c[0] *= rsurface.colormod[0];
7304                 c[1] *= rsurface.colormod[1];
7305                 c[2] *= rsurface.colormod[2];
7306                 c[3] *= rsurface.colormod[3];
7307         }
7308         if (r_refdef.fogenabled)
7309         {
7310                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7311                 {
7312                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7313                         f2 = 1 - f1;
7314                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7315                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7316                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7317                 }
7318         }
7319 //      R_Mesh_ResetTextureState();
7320         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7321         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7322         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7323 }
7324
7325 void R_DrawNoModel(entity_render_t *ent)
7326 {
7327         vec3_t org;
7328         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7329         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7330                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7331         else
7332                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7333 }
7334
7335 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7336 {
7337         vec3_t right1, right2, diff, normal;
7338
7339         VectorSubtract (org2, org1, normal);
7340
7341         // calculate 'right' vector for start
7342         VectorSubtract (r_refdef.view.origin, org1, diff);
7343         CrossProduct (normal, diff, right1);
7344         VectorNormalize (right1);
7345
7346         // calculate 'right' vector for end
7347         VectorSubtract (r_refdef.view.origin, org2, diff);
7348         CrossProduct (normal, diff, right2);
7349         VectorNormalize (right2);
7350
7351         vert[ 0] = org1[0] + width * right1[0];
7352         vert[ 1] = org1[1] + width * right1[1];
7353         vert[ 2] = org1[2] + width * right1[2];
7354         vert[ 3] = org1[0] - width * right1[0];
7355         vert[ 4] = org1[1] - width * right1[1];
7356         vert[ 5] = org1[2] - width * right1[2];
7357         vert[ 6] = org2[0] - width * right2[0];
7358         vert[ 7] = org2[1] - width * right2[1];
7359         vert[ 8] = org2[2] - width * right2[2];
7360         vert[ 9] = org2[0] + width * right2[0];
7361         vert[10] = org2[1] + width * right2[1];
7362         vert[11] = org2[2] + width * right2[2];
7363 }
7364
7365 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)
7366 {
7367         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7368         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7369         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7370         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7371         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7372         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7373         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7374         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7375         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7376         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7377         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7378         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7379 }
7380
7381 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7382 {
7383         int i;
7384         float *vertex3f;
7385         float v[3];
7386         VectorSet(v, x, y, z);
7387         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7388                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7389                         break;
7390         if (i == mesh->numvertices)
7391         {
7392                 if (mesh->numvertices < mesh->maxvertices)
7393                 {
7394                         VectorCopy(v, vertex3f);
7395                         mesh->numvertices++;
7396                 }
7397                 return mesh->numvertices;
7398         }
7399         else
7400                 return i;
7401 }
7402
7403 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7404 {
7405         int i;
7406         int *e, element[3];
7407         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7408         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7409         e = mesh->element3i + mesh->numtriangles * 3;
7410         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7411         {
7412                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7413                 if (mesh->numtriangles < mesh->maxtriangles)
7414                 {
7415                         *e++ = element[0];
7416                         *e++ = element[1];
7417                         *e++ = element[2];
7418                         mesh->numtriangles++;
7419                 }
7420                 element[1] = element[2];
7421         }
7422 }
7423
7424 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7425 {
7426         int i;
7427         int *e, element[3];
7428         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7429         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7430         e = mesh->element3i + mesh->numtriangles * 3;
7431         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7432         {
7433                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7434                 if (mesh->numtriangles < mesh->maxtriangles)
7435                 {
7436                         *e++ = element[0];
7437                         *e++ = element[1];
7438                         *e++ = element[2];
7439                         mesh->numtriangles++;
7440                 }
7441                 element[1] = element[2];
7442         }
7443 }
7444
7445 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7446 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7447 {
7448         int planenum, planenum2;
7449         int w;
7450         int tempnumpoints;
7451         mplane_t *plane, *plane2;
7452         double maxdist;
7453         double temppoints[2][256*3];
7454         // figure out how large a bounding box we need to properly compute this brush
7455         maxdist = 0;
7456         for (w = 0;w < numplanes;w++)
7457                 maxdist = max(maxdist, fabs(planes[w].dist));
7458         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7459         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7460         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7461         {
7462                 w = 0;
7463                 tempnumpoints = 4;
7464                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7465                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7466                 {
7467                         if (planenum2 == planenum)
7468                                 continue;
7469                         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);
7470                         w = !w;
7471                 }
7472                 if (tempnumpoints < 3)
7473                         continue;
7474                 // generate elements forming a triangle fan for this polygon
7475                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7476         }
7477 }
7478
7479 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)
7480 {
7481         texturelayer_t *layer;
7482         layer = t->currentlayers + t->currentnumlayers++;
7483         layer->type = type;
7484         layer->depthmask = depthmask;
7485         layer->blendfunc1 = blendfunc1;
7486         layer->blendfunc2 = blendfunc2;
7487         layer->texture = texture;
7488         layer->texmatrix = *matrix;
7489         layer->color[0] = r;
7490         layer->color[1] = g;
7491         layer->color[2] = b;
7492         layer->color[3] = a;
7493 }
7494
7495 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7496 {
7497         if(parms[0] == 0 && parms[1] == 0)
7498                 return false;
7499         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7500                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7501                         return false;
7502         return true;
7503 }
7504
7505 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7506 {
7507         double index, f;
7508         index = parms[2] + rsurface.shadertime * parms[3];
7509         index -= floor(index);
7510         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7511         {
7512         default:
7513         case Q3WAVEFUNC_NONE:
7514         case Q3WAVEFUNC_NOISE:
7515         case Q3WAVEFUNC_COUNT:
7516                 f = 0;
7517                 break;
7518         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7519         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7520         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7521         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7522         case Q3WAVEFUNC_TRIANGLE:
7523                 index *= 4;
7524                 f = index - floor(index);
7525                 if (index < 1)
7526                 {
7527                         // f = f;
7528                 }
7529                 else if (index < 2)
7530                         f = 1 - f;
7531                 else if (index < 3)
7532                         f = -f;
7533                 else
7534                         f = -(1 - f);
7535                 break;
7536         }
7537         f = parms[0] + parms[1] * f;
7538         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7539                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7540         return (float) f;
7541 }
7542
7543 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7544 {
7545         int w, h, idx;
7546         double f;
7547         double offsetd[2];
7548         float tcmat[12];
7549         matrix4x4_t matrix, temp;
7550         switch(tcmod->tcmod)
7551         {
7552                 case Q3TCMOD_COUNT:
7553                 case Q3TCMOD_NONE:
7554                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7555                                 matrix = r_waterscrollmatrix;
7556                         else
7557                                 matrix = identitymatrix;
7558                         break;
7559                 case Q3TCMOD_ENTITYTRANSLATE:
7560                         // this is used in Q3 to allow the gamecode to control texcoord
7561                         // scrolling on the entity, which is not supported in darkplaces yet.
7562                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7563                         break;
7564                 case Q3TCMOD_ROTATE:
7565                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7566                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7567                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7568                         break;
7569                 case Q3TCMOD_SCALE:
7570                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7571                         break;
7572                 case Q3TCMOD_SCROLL:
7573                         // extra care is needed because of precision breakdown with large values of time
7574                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7575                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7576                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7577                         break;
7578                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7579                         w = (int) tcmod->parms[0];
7580                         h = (int) tcmod->parms[1];
7581                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7582                         f = f - floor(f);
7583                         idx = (int) floor(f * w * h);
7584                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7585                         break;
7586                 case Q3TCMOD_STRETCH:
7587                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7588                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7589                         break;
7590                 case Q3TCMOD_TRANSFORM:
7591                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7592                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7593                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7594                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7595                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7596                         break;
7597                 case Q3TCMOD_TURBULENT:
7598                         // this is handled in the RSurf_PrepareVertices function
7599                         matrix = identitymatrix;
7600                         break;
7601         }
7602         temp = *texmatrix;
7603         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7604 }
7605
7606 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7607 {
7608         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7609         char name[MAX_QPATH];
7610         skinframe_t *skinframe;
7611         unsigned char pixels[296*194];
7612         strlcpy(cache->name, skinname, sizeof(cache->name));
7613         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7614         if (developer_loading.integer)
7615                 Con_Printf("loading %s\n", name);
7616         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7617         if (!skinframe || !skinframe->base)
7618         {
7619                 unsigned char *f;
7620                 fs_offset_t filesize;
7621                 skinframe = NULL;
7622                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7623                 if (f)
7624                 {
7625                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7626                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7627                         Mem_Free(f);
7628                 }
7629         }
7630         cache->skinframe = skinframe;
7631 }
7632
7633 texture_t *R_GetCurrentTexture(texture_t *t)
7634 {
7635         int i;
7636         const entity_render_t *ent = rsurface.entity;
7637         dp_model_t *model = ent->model;
7638         q3shaderinfo_layer_tcmod_t *tcmod;
7639
7640         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7641                 return t->currentframe;
7642         t->update_lastrenderframe = r_textureframe;
7643         t->update_lastrenderentity = (void *)ent;
7644
7645         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7646                 t->camera_entity = ent->entitynumber;
7647         else
7648                 t->camera_entity = 0;
7649
7650         // switch to an alternate material if this is a q1bsp animated material
7651         {
7652                 texture_t *texture = t;
7653                 int s = rsurface.ent_skinnum;
7654                 if ((unsigned int)s >= (unsigned int)model->numskins)
7655                         s = 0;
7656                 if (model->skinscenes)
7657                 {
7658                         if (model->skinscenes[s].framecount > 1)
7659                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7660                         else
7661                                 s = model->skinscenes[s].firstframe;
7662                 }
7663                 if (s > 0)
7664                         t = t + s * model->num_surfaces;
7665                 if (t->animated)
7666                 {
7667                         // use an alternate animation if the entity's frame is not 0,
7668                         // and only if the texture has an alternate animation
7669                         if (rsurface.ent_alttextures && t->anim_total[1])
7670                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7671                         else
7672                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7673                 }
7674                 texture->currentframe = t;
7675         }
7676
7677         // update currentskinframe to be a qw skin or animation frame
7678         if (rsurface.ent_qwskin >= 0)
7679         {
7680                 i = rsurface.ent_qwskin;
7681                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7682                 {
7683                         r_qwskincache_size = cl.maxclients;
7684                         if (r_qwskincache)
7685                                 Mem_Free(r_qwskincache);
7686                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7687                 }
7688                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7689                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7690                 t->currentskinframe = r_qwskincache[i].skinframe;
7691                 if (t->currentskinframe == NULL)
7692                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7693         }
7694         else if (t->numskinframes >= 2)
7695                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7696         if (t->backgroundnumskinframes >= 2)
7697                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7698
7699         t->currentmaterialflags = t->basematerialflags;
7700         t->currentalpha = rsurface.colormod[3];
7701         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7702                 t->currentalpha *= r_wateralpha.value;
7703         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7704                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7705         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7706                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7707         if (!(rsurface.ent_flags & RENDER_LIGHT))
7708                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7709         else if (FAKELIGHT_ENABLED)
7710         {
7711                 // no modellight if using fakelight for the map
7712         }
7713         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7714         {
7715                 // pick a model lighting mode
7716                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7717                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7718                 else
7719                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7720         }
7721         if (rsurface.ent_flags & RENDER_ADDITIVE)
7722                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7723         else if (t->currentalpha < 1)
7724                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7725         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7726                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7727         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7728                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7729         if (t->backgroundnumskinframes)
7730                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7731         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7732         {
7733                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7734                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7735         }
7736         else
7737                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7738         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7739         {
7740                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7741                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7742         }
7743         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7744                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7745
7746         // there is no tcmod
7747         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7748         {
7749                 t->currenttexmatrix = r_waterscrollmatrix;
7750                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7751         }
7752         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7753         {
7754                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7755                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7756         }
7757
7758         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7759                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7760         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7761                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7762
7763         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7764         if (t->currentskinframe->qpixels)
7765                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7766         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7767         if (!t->basetexture)
7768                 t->basetexture = r_texture_notexture;
7769         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7770         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7771         t->nmaptexture = t->currentskinframe->nmap;
7772         if (!t->nmaptexture)
7773                 t->nmaptexture = r_texture_blanknormalmap;
7774         t->glosstexture = r_texture_black;
7775         t->glowtexture = t->currentskinframe->glow;
7776         t->fogtexture = t->currentskinframe->fog;
7777         t->reflectmasktexture = t->currentskinframe->reflect;
7778         if (t->backgroundnumskinframes)
7779         {
7780                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7781                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7782                 t->backgroundglosstexture = r_texture_black;
7783                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7784                 if (!t->backgroundnmaptexture)
7785                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7786         }
7787         else
7788         {
7789                 t->backgroundbasetexture = r_texture_white;
7790                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7791                 t->backgroundglosstexture = r_texture_black;
7792                 t->backgroundglowtexture = NULL;
7793         }
7794         t->specularpower = r_shadow_glossexponent.value;
7795         // TODO: store reference values for these in the texture?
7796         t->specularscale = 0;
7797         if (r_shadow_gloss.integer > 0)
7798         {
7799                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7800                 {
7801                         if (r_shadow_glossintensity.value > 0)
7802                         {
7803                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7804                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7805                                 t->specularscale = r_shadow_glossintensity.value;
7806                         }
7807                 }
7808                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7809                 {
7810                         t->glosstexture = r_texture_white;
7811                         t->backgroundglosstexture = r_texture_white;
7812                         t->specularscale = r_shadow_gloss2intensity.value;
7813                         t->specularpower = r_shadow_gloss2exponent.value;
7814                 }
7815         }
7816         t->specularscale *= t->specularscalemod;
7817         t->specularpower *= t->specularpowermod;
7818
7819         // lightmaps mode looks bad with dlights using actual texturing, so turn
7820         // off the colormap and glossmap, but leave the normalmap on as it still
7821         // accurately represents the shading involved
7822         if (gl_lightmaps.integer)
7823         {
7824                 t->basetexture = r_texture_grey128;
7825                 t->pantstexture = r_texture_black;
7826                 t->shirttexture = r_texture_black;
7827                 t->nmaptexture = r_texture_blanknormalmap;
7828                 t->glosstexture = r_texture_black;
7829                 t->glowtexture = NULL;
7830                 t->fogtexture = NULL;
7831                 t->reflectmasktexture = NULL;
7832                 t->backgroundbasetexture = NULL;
7833                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7834                 t->backgroundglosstexture = r_texture_black;
7835                 t->backgroundglowtexture = NULL;
7836                 t->specularscale = 0;
7837                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7838         }
7839
7840         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7841         VectorClear(t->dlightcolor);
7842         t->currentnumlayers = 0;
7843         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7844         {
7845                 int blendfunc1, blendfunc2;
7846                 qboolean depthmask;
7847                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7848                 {
7849                         blendfunc1 = GL_SRC_ALPHA;
7850                         blendfunc2 = GL_ONE;
7851                 }
7852                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7853                 {
7854                         blendfunc1 = GL_SRC_ALPHA;
7855                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7856                 }
7857                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7858                 {
7859                         blendfunc1 = t->customblendfunc[0];
7860                         blendfunc2 = t->customblendfunc[1];
7861                 }
7862                 else
7863                 {
7864                         blendfunc1 = GL_ONE;
7865                         blendfunc2 = GL_ZERO;
7866                 }
7867                 // don't colormod evilblend textures
7868                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7869                         VectorSet(t->lightmapcolor, 1, 1, 1);
7870                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7871                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7872                 {
7873                         // fullbright is not affected by r_refdef.lightmapintensity
7874                         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]);
7875                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7876                                 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]);
7877                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7878                                 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]);
7879                 }
7880                 else
7881                 {
7882                         vec3_t ambientcolor;
7883                         float colorscale;
7884                         // set the color tint used for lights affecting this surface
7885                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7886                         colorscale = 2;
7887                         // q3bsp has no lightmap updates, so the lightstylevalue that
7888                         // would normally be baked into the lightmap must be
7889                         // applied to the color
7890                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7891                         if (model->type == mod_brushq3)
7892                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7893                         colorscale *= r_refdef.lightmapintensity;
7894                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7895                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7896                         // basic lit geometry
7897                         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]);
7898                         // add pants/shirt if needed
7899                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7900                                 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]);
7901                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7902                                 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]);
7903                         // now add ambient passes if needed
7904                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7905                         {
7906                                 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]);
7907                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7908                                         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]);
7909                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7910                                         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]);
7911                         }
7912                 }
7913                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7914                         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]);
7915                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7916                 {
7917                         // if this is opaque use alpha blend which will darken the earlier
7918                         // passes cheaply.
7919                         //
7920                         // if this is an alpha blended material, all the earlier passes
7921                         // were darkened by fog already, so we only need to add the fog
7922                         // color ontop through the fog mask texture
7923                         //
7924                         // if this is an additive blended material, all the earlier passes
7925                         // were darkened by fog already, and we should not add fog color
7926                         // (because the background was not darkened, there is no fog color
7927                         // that was lost behind it).
7928                         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]);
7929                 }
7930         }
7931
7932         return t->currentframe;
7933 }
7934
7935 rsurfacestate_t rsurface;
7936
7937 void RSurf_ActiveWorldEntity(void)
7938 {
7939         dp_model_t *model = r_refdef.scene.worldmodel;
7940         //if (rsurface.entity == r_refdef.scene.worldentity)
7941         //      return;
7942         rsurface.entity = r_refdef.scene.worldentity;
7943         rsurface.skeleton = NULL;
7944         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7945         rsurface.ent_skinnum = 0;
7946         rsurface.ent_qwskin = -1;
7947         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7948         rsurface.shadertime = r_refdef.scene.time;
7949         rsurface.matrix = identitymatrix;
7950         rsurface.inversematrix = identitymatrix;
7951         rsurface.matrixscale = 1;
7952         rsurface.inversematrixscale = 1;
7953         R_EntityMatrix(&identitymatrix);
7954         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7955         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7956         rsurface.fograngerecip = r_refdef.fograngerecip;
7957         rsurface.fogheightfade = r_refdef.fogheightfade;
7958         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7959         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7960         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7961         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7962         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7963         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7964         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7965         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7966         rsurface.colormod[3] = 1;
7967         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);
7968         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7969         rsurface.frameblend[0].lerp = 1;
7970         rsurface.ent_alttextures = false;
7971         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7972         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7973         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7974         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7975         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7976         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7977         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7978         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7979         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7980         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7981         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7982         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7983         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7984         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7985         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7986         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7987         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7988         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7989         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7990         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7991         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7992         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7993         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7994         rsurface.modelelement3i = model->surfmesh.data_element3i;
7995         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7996         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7997         rsurface.modelelement3s = model->surfmesh.data_element3s;
7998         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7999         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8000         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8001         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8002         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8003         rsurface.modelsurfaces = model->data_surfaces;
8004         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8005         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8006         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8007         rsurface.modelgeneratedvertex = false;
8008         rsurface.batchgeneratedvertex = false;
8009         rsurface.batchfirstvertex = 0;
8010         rsurface.batchnumvertices = 0;
8011         rsurface.batchfirsttriangle = 0;
8012         rsurface.batchnumtriangles = 0;
8013         rsurface.batchvertex3f  = NULL;
8014         rsurface.batchvertex3f_vertexbuffer = NULL;
8015         rsurface.batchvertex3f_bufferoffset = 0;
8016         rsurface.batchsvector3f = NULL;
8017         rsurface.batchsvector3f_vertexbuffer = NULL;
8018         rsurface.batchsvector3f_bufferoffset = 0;
8019         rsurface.batchtvector3f = NULL;
8020         rsurface.batchtvector3f_vertexbuffer = NULL;
8021         rsurface.batchtvector3f_bufferoffset = 0;
8022         rsurface.batchnormal3f  = NULL;
8023         rsurface.batchnormal3f_vertexbuffer = NULL;
8024         rsurface.batchnormal3f_bufferoffset = 0;
8025         rsurface.batchlightmapcolor4f = NULL;
8026         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8027         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8028         rsurface.batchtexcoordtexture2f = NULL;
8029         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8030         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8031         rsurface.batchtexcoordlightmap2f = NULL;
8032         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8033         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8034         rsurface.batchvertexmesh = NULL;
8035         rsurface.batchvertexmeshbuffer = NULL;
8036         rsurface.batchvertex3fbuffer = NULL;
8037         rsurface.batchelement3i = NULL;
8038         rsurface.batchelement3i_indexbuffer = NULL;
8039         rsurface.batchelement3i_bufferoffset = 0;
8040         rsurface.batchelement3s = NULL;
8041         rsurface.batchelement3s_indexbuffer = NULL;
8042         rsurface.batchelement3s_bufferoffset = 0;
8043         rsurface.passcolor4f = NULL;
8044         rsurface.passcolor4f_vertexbuffer = NULL;
8045         rsurface.passcolor4f_bufferoffset = 0;
8046 }
8047
8048 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8049 {
8050         dp_model_t *model = ent->model;
8051         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8052         //      return;
8053         rsurface.entity = (entity_render_t *)ent;
8054         rsurface.skeleton = ent->skeleton;
8055         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8056         rsurface.ent_skinnum = ent->skinnum;
8057         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;
8058         rsurface.ent_flags = ent->flags;
8059         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8060         rsurface.matrix = ent->matrix;
8061         rsurface.inversematrix = ent->inversematrix;
8062         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8063         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8064         R_EntityMatrix(&rsurface.matrix);
8065         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8066         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8067         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8068         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8069         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8070         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8071         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8072         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8073         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8074         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8075         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8076         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8077         rsurface.colormod[3] = ent->alpha;
8078         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8079         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8080         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8081         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8082         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8083         if (ent->model->brush.submodel && !prepass)
8084         {
8085                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8086                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8087         }
8088         if (model->surfmesh.isanimated && model->AnimateVertices)
8089         {
8090                 if (ent->animcache_vertex3f)
8091                 {
8092                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8093                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8094                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8095                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8096                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8097                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8098                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8099                 }
8100                 else if (wanttangents)
8101                 {
8102                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8103                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8104                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8105                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8106                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8107                         rsurface.modelvertexmesh = NULL;
8108                         rsurface.modelvertexmeshbuffer = NULL;
8109                         rsurface.modelvertex3fbuffer = NULL;
8110                 }
8111                 else if (wantnormals)
8112                 {
8113                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8114                         rsurface.modelsvector3f = NULL;
8115                         rsurface.modeltvector3f = NULL;
8116                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8117                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8118                         rsurface.modelvertexmesh = NULL;
8119                         rsurface.modelvertexmeshbuffer = NULL;
8120                         rsurface.modelvertex3fbuffer = NULL;
8121                 }
8122                 else
8123                 {
8124                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8125                         rsurface.modelsvector3f = NULL;
8126                         rsurface.modeltvector3f = NULL;
8127                         rsurface.modelnormal3f = NULL;
8128                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8129                         rsurface.modelvertexmesh = NULL;
8130                         rsurface.modelvertexmeshbuffer = NULL;
8131                         rsurface.modelvertex3fbuffer = NULL;
8132                 }
8133                 rsurface.modelvertex3f_vertexbuffer = 0;
8134                 rsurface.modelvertex3f_bufferoffset = 0;
8135                 rsurface.modelsvector3f_vertexbuffer = 0;
8136                 rsurface.modelsvector3f_bufferoffset = 0;
8137                 rsurface.modeltvector3f_vertexbuffer = 0;
8138                 rsurface.modeltvector3f_bufferoffset = 0;
8139                 rsurface.modelnormal3f_vertexbuffer = 0;
8140                 rsurface.modelnormal3f_bufferoffset = 0;
8141                 rsurface.modelgeneratedvertex = true;
8142         }
8143         else
8144         {
8145                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8146                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8147                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8148                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8149                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8150                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8151                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8152                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8153                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8154                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8155                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8156                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8157                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8158                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8159                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8160                 rsurface.modelgeneratedvertex = false;
8161         }
8162         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8163         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8164         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8165         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8166         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8167         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8168         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8169         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8170         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8171         rsurface.modelelement3i = model->surfmesh.data_element3i;
8172         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8173         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8174         rsurface.modelelement3s = model->surfmesh.data_element3s;
8175         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8176         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8177         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8178         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8179         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8180         rsurface.modelsurfaces = model->data_surfaces;
8181         rsurface.batchgeneratedvertex = false;
8182         rsurface.batchfirstvertex = 0;
8183         rsurface.batchnumvertices = 0;
8184         rsurface.batchfirsttriangle = 0;
8185         rsurface.batchnumtriangles = 0;
8186         rsurface.batchvertex3f  = NULL;
8187         rsurface.batchvertex3f_vertexbuffer = NULL;
8188         rsurface.batchvertex3f_bufferoffset = 0;
8189         rsurface.batchsvector3f = NULL;
8190         rsurface.batchsvector3f_vertexbuffer = NULL;
8191         rsurface.batchsvector3f_bufferoffset = 0;
8192         rsurface.batchtvector3f = NULL;
8193         rsurface.batchtvector3f_vertexbuffer = NULL;
8194         rsurface.batchtvector3f_bufferoffset = 0;
8195         rsurface.batchnormal3f  = NULL;
8196         rsurface.batchnormal3f_vertexbuffer = NULL;
8197         rsurface.batchnormal3f_bufferoffset = 0;
8198         rsurface.batchlightmapcolor4f = NULL;
8199         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8200         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8201         rsurface.batchtexcoordtexture2f = NULL;
8202         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8203         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8204         rsurface.batchtexcoordlightmap2f = NULL;
8205         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8206         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8207         rsurface.batchvertexmesh = NULL;
8208         rsurface.batchvertexmeshbuffer = NULL;
8209         rsurface.batchvertex3fbuffer = NULL;
8210         rsurface.batchelement3i = NULL;
8211         rsurface.batchelement3i_indexbuffer = NULL;
8212         rsurface.batchelement3i_bufferoffset = 0;
8213         rsurface.batchelement3s = NULL;
8214         rsurface.batchelement3s_indexbuffer = NULL;
8215         rsurface.batchelement3s_bufferoffset = 0;
8216         rsurface.passcolor4f = NULL;
8217         rsurface.passcolor4f_vertexbuffer = NULL;
8218         rsurface.passcolor4f_bufferoffset = 0;
8219 }
8220
8221 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)
8222 {
8223         rsurface.entity = r_refdef.scene.worldentity;
8224         rsurface.skeleton = NULL;
8225         rsurface.ent_skinnum = 0;
8226         rsurface.ent_qwskin = -1;
8227         rsurface.ent_flags = entflags;
8228         rsurface.shadertime = r_refdef.scene.time - shadertime;
8229         rsurface.modelnumvertices = numvertices;
8230         rsurface.modelnumtriangles = numtriangles;
8231         rsurface.matrix = *matrix;
8232         rsurface.inversematrix = *inversematrix;
8233         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8234         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8235         R_EntityMatrix(&rsurface.matrix);
8236         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8237         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8238         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8239         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8240         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8241         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8242         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8243         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8244         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8245         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8246         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8247         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8248         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);
8249         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8250         rsurface.frameblend[0].lerp = 1;
8251         rsurface.ent_alttextures = false;
8252         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8253         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8254         if (wanttangents)
8255         {
8256                 rsurface.modelvertex3f = (float *)vertex3f;
8257                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8258                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8259                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8260         }
8261         else if (wantnormals)
8262         {
8263                 rsurface.modelvertex3f = (float *)vertex3f;
8264                 rsurface.modelsvector3f = NULL;
8265                 rsurface.modeltvector3f = NULL;
8266                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8267         }
8268         else
8269         {
8270                 rsurface.modelvertex3f = (float *)vertex3f;
8271                 rsurface.modelsvector3f = NULL;
8272                 rsurface.modeltvector3f = NULL;
8273                 rsurface.modelnormal3f = NULL;
8274         }
8275         rsurface.modelvertexmesh = NULL;
8276         rsurface.modelvertexmeshbuffer = NULL;
8277         rsurface.modelvertex3fbuffer = NULL;
8278         rsurface.modelvertex3f_vertexbuffer = 0;
8279         rsurface.modelvertex3f_bufferoffset = 0;
8280         rsurface.modelsvector3f_vertexbuffer = 0;
8281         rsurface.modelsvector3f_bufferoffset = 0;
8282         rsurface.modeltvector3f_vertexbuffer = 0;
8283         rsurface.modeltvector3f_bufferoffset = 0;
8284         rsurface.modelnormal3f_vertexbuffer = 0;
8285         rsurface.modelnormal3f_bufferoffset = 0;
8286         rsurface.modelgeneratedvertex = true;
8287         rsurface.modellightmapcolor4f  = (float *)color4f;
8288         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8289         rsurface.modellightmapcolor4f_bufferoffset = 0;
8290         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8291         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8292         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8293         rsurface.modeltexcoordlightmap2f  = NULL;
8294         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8295         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8296         rsurface.modelelement3i = (int *)element3i;
8297         rsurface.modelelement3i_indexbuffer = NULL;
8298         rsurface.modelelement3i_bufferoffset = 0;
8299         rsurface.modelelement3s = (unsigned short *)element3s;
8300         rsurface.modelelement3s_indexbuffer = NULL;
8301         rsurface.modelelement3s_bufferoffset = 0;
8302         rsurface.modellightmapoffsets = NULL;
8303         rsurface.modelsurfaces = NULL;
8304         rsurface.batchgeneratedvertex = false;
8305         rsurface.batchfirstvertex = 0;
8306         rsurface.batchnumvertices = 0;
8307         rsurface.batchfirsttriangle = 0;
8308         rsurface.batchnumtriangles = 0;
8309         rsurface.batchvertex3f  = NULL;
8310         rsurface.batchvertex3f_vertexbuffer = NULL;
8311         rsurface.batchvertex3f_bufferoffset = 0;
8312         rsurface.batchsvector3f = NULL;
8313         rsurface.batchsvector3f_vertexbuffer = NULL;
8314         rsurface.batchsvector3f_bufferoffset = 0;
8315         rsurface.batchtvector3f = NULL;
8316         rsurface.batchtvector3f_vertexbuffer = NULL;
8317         rsurface.batchtvector3f_bufferoffset = 0;
8318         rsurface.batchnormal3f  = NULL;
8319         rsurface.batchnormal3f_vertexbuffer = NULL;
8320         rsurface.batchnormal3f_bufferoffset = 0;
8321         rsurface.batchlightmapcolor4f = NULL;
8322         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8323         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8324         rsurface.batchtexcoordtexture2f = NULL;
8325         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8326         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8327         rsurface.batchtexcoordlightmap2f = NULL;
8328         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8329         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8330         rsurface.batchvertexmesh = NULL;
8331         rsurface.batchvertexmeshbuffer = NULL;
8332         rsurface.batchvertex3fbuffer = NULL;
8333         rsurface.batchelement3i = NULL;
8334         rsurface.batchelement3i_indexbuffer = NULL;
8335         rsurface.batchelement3i_bufferoffset = 0;
8336         rsurface.batchelement3s = NULL;
8337         rsurface.batchelement3s_indexbuffer = NULL;
8338         rsurface.batchelement3s_bufferoffset = 0;
8339         rsurface.passcolor4f = NULL;
8340         rsurface.passcolor4f_vertexbuffer = NULL;
8341         rsurface.passcolor4f_bufferoffset = 0;
8342
8343         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8344         {
8345                 if ((wantnormals || wanttangents) && !normal3f)
8346                 {
8347                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8348                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8349                 }
8350                 if (wanttangents && !svector3f)
8351                 {
8352                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8353                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8354                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8355                 }
8356         }
8357 }
8358
8359 float RSurf_FogPoint(const float *v)
8360 {
8361         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8362         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8363         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8364         float FogHeightFade = r_refdef.fogheightfade;
8365         float fogfrac;
8366         unsigned int fogmasktableindex;
8367         if (r_refdef.fogplaneviewabove)
8368                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8369         else
8370                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8371         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8372         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8373 }
8374
8375 float RSurf_FogVertex(const float *v)
8376 {
8377         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8378         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8379         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8380         float FogHeightFade = rsurface.fogheightfade;
8381         float fogfrac;
8382         unsigned int fogmasktableindex;
8383         if (r_refdef.fogplaneviewabove)
8384                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8385         else
8386                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8387         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8388         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8389 }
8390
8391 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8392 {
8393         int i;
8394         for (i = 0;i < numelements;i++)
8395                 outelement3i[i] = inelement3i[i] + adjust;
8396 }
8397
8398 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8399 extern cvar_t gl_vbo;
8400 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8401 {
8402         int deformindex;
8403         int firsttriangle;
8404         int numtriangles;
8405         int firstvertex;
8406         int endvertex;
8407         int numvertices;
8408         int surfacefirsttriangle;
8409         int surfacenumtriangles;
8410         int surfacefirstvertex;
8411         int surfaceendvertex;
8412         int surfacenumvertices;
8413         int batchnumvertices;
8414         int batchnumtriangles;
8415         int needsupdate;
8416         int i, j;
8417         qboolean gaps;
8418         qboolean dynamicvertex;
8419         float amplitude;
8420         float animpos;
8421         float scale;
8422         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8423         float waveparms[4];
8424         q3shaderinfo_deform_t *deform;
8425         const msurface_t *surface, *firstsurface;
8426         r_vertexmesh_t *vertexmesh;
8427         if (!texturenumsurfaces)
8428                 return;
8429         // find vertex range of this surface batch
8430         gaps = false;
8431         firstsurface = texturesurfacelist[0];
8432         firsttriangle = firstsurface->num_firsttriangle;
8433         batchnumvertices = 0;
8434         batchnumtriangles = 0;
8435         firstvertex = endvertex = firstsurface->num_firstvertex;
8436         for (i = 0;i < texturenumsurfaces;i++)
8437         {
8438                 surface = texturesurfacelist[i];
8439                 if (surface != firstsurface + i)
8440                         gaps = true;
8441                 surfacefirstvertex = surface->num_firstvertex;
8442                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8443                 surfacenumvertices = surface->num_vertices;
8444                 surfacenumtriangles = surface->num_triangles;
8445                 if (firstvertex > surfacefirstvertex)
8446                         firstvertex = surfacefirstvertex;
8447                 if (endvertex < surfaceendvertex)
8448                         endvertex = surfaceendvertex;
8449                 batchnumvertices += surfacenumvertices;
8450                 batchnumtriangles += surfacenumtriangles;
8451         }
8452
8453         // we now know the vertex range used, and if there are any gaps in it
8454         rsurface.batchfirstvertex = firstvertex;
8455         rsurface.batchnumvertices = endvertex - firstvertex;
8456         rsurface.batchfirsttriangle = firsttriangle;
8457         rsurface.batchnumtriangles = batchnumtriangles;
8458
8459         // this variable holds flags for which properties have been updated that
8460         // may require regenerating vertexmesh array...
8461         needsupdate = 0;
8462
8463         // check if any dynamic vertex processing must occur
8464         dynamicvertex = false;
8465
8466         // if there is a chance of animated vertex colors, it's a dynamic batch
8467         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8468         {
8469                 dynamicvertex = true;
8470                 batchneed |= BATCHNEED_NOGAPS;
8471                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8472         }
8473
8474         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8475         {
8476                 switch (deform->deform)
8477                 {
8478                 default:
8479                 case Q3DEFORM_PROJECTIONSHADOW:
8480                 case Q3DEFORM_TEXT0:
8481                 case Q3DEFORM_TEXT1:
8482                 case Q3DEFORM_TEXT2:
8483                 case Q3DEFORM_TEXT3:
8484                 case Q3DEFORM_TEXT4:
8485                 case Q3DEFORM_TEXT5:
8486                 case Q3DEFORM_TEXT6:
8487                 case Q3DEFORM_TEXT7:
8488                 case Q3DEFORM_NONE:
8489                         break;
8490                 case Q3DEFORM_AUTOSPRITE:
8491                         dynamicvertex = true;
8492                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8493                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8494                         break;
8495                 case Q3DEFORM_AUTOSPRITE2:
8496                         dynamicvertex = true;
8497                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8498                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8499                         break;
8500                 case Q3DEFORM_NORMAL:
8501                         dynamicvertex = true;
8502                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8503                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8504                         break;
8505                 case Q3DEFORM_WAVE:
8506                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8507                                 break; // if wavefunc is a nop, ignore this transform
8508                         dynamicvertex = true;
8509                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8510                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8511                         break;
8512                 case Q3DEFORM_BULGE:
8513                         dynamicvertex = true;
8514                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8515                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8516                         break;
8517                 case Q3DEFORM_MOVE:
8518                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8519                                 break; // if wavefunc is a nop, ignore this transform
8520                         dynamicvertex = true;
8521                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8522                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8523                         break;
8524                 }
8525         }
8526         switch(rsurface.texture->tcgen.tcgen)
8527         {
8528         default:
8529         case Q3TCGEN_TEXTURE:
8530                 break;
8531         case Q3TCGEN_LIGHTMAP:
8532                 dynamicvertex = true;
8533                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8534                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8535                 break;
8536         case Q3TCGEN_VECTOR:
8537                 dynamicvertex = true;
8538                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8539                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8540                 break;
8541         case Q3TCGEN_ENVIRONMENT:
8542                 dynamicvertex = true;
8543                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8544                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8545                 break;
8546         }
8547         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8548         {
8549                 dynamicvertex = true;
8550                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8551                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8552         }
8553
8554         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8555         {
8556                 dynamicvertex = true;
8557                 batchneed |= BATCHNEED_NOGAPS;
8558                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8559         }
8560
8561         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8562         {
8563                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8564                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8565                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8566                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8567                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8568                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8569                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8570         }
8571
8572         // when the model data has no vertex buffer (dynamic mesh), we need to
8573         // eliminate gaps
8574         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8575                 batchneed |= BATCHNEED_NOGAPS;
8576
8577         // if needsupdate, we have to do a dynamic vertex batch for sure
8578         if (needsupdate & batchneed)
8579                 dynamicvertex = true;
8580
8581         // see if we need to build vertexmesh from arrays
8582         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8583                 dynamicvertex = true;
8584
8585         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8586         // also some drivers strongly dislike firstvertex
8587         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8588                 dynamicvertex = true;
8589
8590         rsurface.batchvertex3f = rsurface.modelvertex3f;
8591         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8592         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8593         rsurface.batchsvector3f = rsurface.modelsvector3f;
8594         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8595         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8596         rsurface.batchtvector3f = rsurface.modeltvector3f;
8597         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8598         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8599         rsurface.batchnormal3f = rsurface.modelnormal3f;
8600         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8601         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8602         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8603         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8604         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8605         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8606         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8607         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8608         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8609         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8610         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8611         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8612         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8613         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8614         rsurface.batchelement3i = rsurface.modelelement3i;
8615         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8616         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8617         rsurface.batchelement3s = rsurface.modelelement3s;
8618         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8619         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8620
8621         // if any dynamic vertex processing has to occur in software, we copy the
8622         // entire surface list together before processing to rebase the vertices
8623         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8624         //
8625         // if any gaps exist and we do not have a static vertex buffer, we have to
8626         // copy the surface list together to avoid wasting upload bandwidth on the
8627         // vertices in the gaps.
8628         //
8629         // if gaps exist and we have a static vertex buffer, we still have to
8630         // combine the index buffer ranges into one dynamic index buffer.
8631         //
8632         // in all cases we end up with data that can be drawn in one call.
8633
8634         if (!dynamicvertex)
8635         {
8636                 // static vertex data, just set pointers...
8637                 rsurface.batchgeneratedvertex = false;
8638                 // if there are gaps, we want to build a combined index buffer,
8639                 // otherwise use the original static buffer with an appropriate offset
8640                 if (gaps)
8641                 {
8642                         // build a new triangle elements array for this batch
8643                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8644                         rsurface.batchfirsttriangle = 0;
8645                         numtriangles = 0;
8646                         for (i = 0;i < texturenumsurfaces;i++)
8647                         {
8648                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8649                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8650                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8651                                 numtriangles += surfacenumtriangles;
8652                         }
8653                         rsurface.batchelement3i_indexbuffer = NULL;
8654                         rsurface.batchelement3i_bufferoffset = 0;
8655                         rsurface.batchelement3s = NULL;
8656                         rsurface.batchelement3s_indexbuffer = NULL;
8657                         rsurface.batchelement3s_bufferoffset = 0;
8658                         if (endvertex <= 65536)
8659                         {
8660                                 // make a 16bit (unsigned short) index array if possible
8661                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8662                                 for (i = 0;i < numtriangles*3;i++)
8663                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8664                         }
8665                 }
8666                 return;
8667         }
8668
8669         // something needs software processing, do it for real...
8670         // we only directly handle separate array data in this case and then
8671         // generate interleaved data if needed...
8672         rsurface.batchgeneratedvertex = true;
8673
8674         // now copy the vertex data into a combined array and make an index array
8675         // (this is what Quake3 does all the time)
8676         //if (gaps || rsurface.batchfirstvertex)
8677         {
8678                 rsurface.batchvertex3fbuffer = NULL;
8679                 rsurface.batchvertexmesh = NULL;
8680                 rsurface.batchvertexmeshbuffer = NULL;
8681                 rsurface.batchvertex3f = NULL;
8682                 rsurface.batchvertex3f_vertexbuffer = NULL;
8683                 rsurface.batchvertex3f_bufferoffset = 0;
8684                 rsurface.batchsvector3f = NULL;
8685                 rsurface.batchsvector3f_vertexbuffer = NULL;
8686                 rsurface.batchsvector3f_bufferoffset = 0;
8687                 rsurface.batchtvector3f = NULL;
8688                 rsurface.batchtvector3f_vertexbuffer = NULL;
8689                 rsurface.batchtvector3f_bufferoffset = 0;
8690                 rsurface.batchnormal3f = NULL;
8691                 rsurface.batchnormal3f_vertexbuffer = NULL;
8692                 rsurface.batchnormal3f_bufferoffset = 0;
8693                 rsurface.batchlightmapcolor4f = NULL;
8694                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8695                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8696                 rsurface.batchtexcoordtexture2f = NULL;
8697                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8698                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8699                 rsurface.batchtexcoordlightmap2f = NULL;
8700                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8701                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8702                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8703                 rsurface.batchelement3i_indexbuffer = NULL;
8704                 rsurface.batchelement3i_bufferoffset = 0;
8705                 rsurface.batchelement3s = NULL;
8706                 rsurface.batchelement3s_indexbuffer = NULL;
8707                 rsurface.batchelement3s_bufferoffset = 0;
8708                 // we'll only be setting up certain arrays as needed
8709                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8710                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8711                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8712                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8713                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8714                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8715                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8716                 {
8717                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8718                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8719                 }
8720                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8721                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8722                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8723                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8724                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8725                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8726                 numvertices = 0;
8727                 numtriangles = 0;
8728                 for (i = 0;i < texturenumsurfaces;i++)
8729                 {
8730                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8731                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8732                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8733                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8734                         // copy only the data requested
8735                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8736                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8737                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8738                         {
8739                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8740                                 {
8741                                         if (rsurface.batchvertex3f)
8742                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8743                                         else
8744                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8745                                 }
8746                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8747                                 {
8748                                         if (rsurface.modelnormal3f)
8749                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8750                                         else
8751                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8752                                 }
8753                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8754                                 {
8755                                         if (rsurface.modelsvector3f)
8756                                         {
8757                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8758                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8759                                         }
8760                                         else
8761                                         {
8762                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8763                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8764                                         }
8765                                 }
8766                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8767                                 {
8768                                         if (rsurface.modellightmapcolor4f)
8769                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8770                                         else
8771                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8772                                 }
8773                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8774                                 {
8775                                         if (rsurface.modeltexcoordtexture2f)
8776                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8777                                         else
8778                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8779                                 }
8780                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8781                                 {
8782                                         if (rsurface.modeltexcoordlightmap2f)
8783                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8784                                         else
8785                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8786                                 }
8787                         }
8788                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8789                         numvertices += surfacenumvertices;
8790                         numtriangles += surfacenumtriangles;
8791                 }
8792
8793                 // generate a 16bit index array as well if possible
8794                 // (in general, dynamic batches fit)
8795                 if (numvertices <= 65536)
8796                 {
8797                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8798                         for (i = 0;i < numtriangles*3;i++)
8799                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8800                 }
8801
8802                 // since we've copied everything, the batch now starts at 0
8803                 rsurface.batchfirstvertex = 0;
8804                 rsurface.batchnumvertices = batchnumvertices;
8805                 rsurface.batchfirsttriangle = 0;
8806                 rsurface.batchnumtriangles = batchnumtriangles;
8807         }
8808
8809         // q1bsp surfaces rendered in vertex color mode have to have colors
8810         // calculated based on lightstyles
8811         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8812         {
8813                 // generate color arrays for the surfaces in this list
8814                 int c[4];
8815                 int scale;
8816                 int size3;
8817                 const int *offsets;
8818                 const unsigned char *lm;
8819                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8820                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8821                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8822                 numvertices = 0;
8823                 for (i = 0;i < texturenumsurfaces;i++)
8824                 {
8825                         surface = texturesurfacelist[i];
8826                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8827                         surfacenumvertices = surface->num_vertices;
8828                         if (surface->lightmapinfo->samples)
8829                         {
8830                                 for (j = 0;j < surfacenumvertices;j++)
8831                                 {
8832                                         lm = surface->lightmapinfo->samples + offsets[j];
8833                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8834                                         VectorScale(lm, scale, c);
8835                                         if (surface->lightmapinfo->styles[1] != 255)
8836                                         {
8837                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8838                                                 lm += size3;
8839                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8840                                                 VectorMA(c, scale, lm, c);
8841                                                 if (surface->lightmapinfo->styles[2] != 255)
8842                                                 {
8843                                                         lm += size3;
8844                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8845                                                         VectorMA(c, scale, lm, c);
8846                                                         if (surface->lightmapinfo->styles[3] != 255)
8847                                                         {
8848                                                                 lm += size3;
8849                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8850                                                                 VectorMA(c, scale, lm, c);
8851                                                         }
8852                                                 }
8853                                         }
8854                                         c[0] >>= 7;
8855                                         c[1] >>= 7;
8856                                         c[2] >>= 7;
8857                                         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);
8858                                         numvertices++;
8859                                 }
8860                         }
8861                         else
8862                         {
8863                                 for (j = 0;j < surfacenumvertices;j++)
8864                                 {
8865                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8866                                         numvertices++;
8867                                 }
8868                         }
8869                 }
8870         }
8871
8872         // if vertices are deformed (sprite flares and things in maps, possibly
8873         // water waves, bulges and other deformations), modify the copied vertices
8874         // in place
8875         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8876         {
8877                 switch (deform->deform)
8878                 {
8879                 default:
8880                 case Q3DEFORM_PROJECTIONSHADOW:
8881                 case Q3DEFORM_TEXT0:
8882                 case Q3DEFORM_TEXT1:
8883                 case Q3DEFORM_TEXT2:
8884                 case Q3DEFORM_TEXT3:
8885                 case Q3DEFORM_TEXT4:
8886                 case Q3DEFORM_TEXT5:
8887                 case Q3DEFORM_TEXT6:
8888                 case Q3DEFORM_TEXT7:
8889                 case Q3DEFORM_NONE:
8890                         break;
8891                 case Q3DEFORM_AUTOSPRITE:
8892                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8893                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8894                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8895                         VectorNormalize(newforward);
8896                         VectorNormalize(newright);
8897                         VectorNormalize(newup);
8898 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8899 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8900 //                      rsurface.batchvertex3f_bufferoffset = 0;
8901 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8902 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8903 //                      rsurface.batchsvector3f_bufferoffset = 0;
8904 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8905 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8906 //                      rsurface.batchtvector3f_bufferoffset = 0;
8907 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8908 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8909 //                      rsurface.batchnormal3f_bufferoffset = 0;
8910                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8911                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8912                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8913                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8914                                 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);
8915                         // a single autosprite surface can contain multiple sprites...
8916                         for (j = 0;j < batchnumvertices - 3;j += 4)
8917                         {
8918                                 VectorClear(center);
8919                                 for (i = 0;i < 4;i++)
8920                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8921                                 VectorScale(center, 0.25f, center);
8922                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8923                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8924                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8925                                 for (i = 0;i < 4;i++)
8926                                 {
8927                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8928                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8929                                 }
8930                         }
8931                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8932                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8933                         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);
8934                         break;
8935                 case Q3DEFORM_AUTOSPRITE2:
8936                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8937                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8938                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8939                         VectorNormalize(newforward);
8940                         VectorNormalize(newright);
8941                         VectorNormalize(newup);
8942 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8943 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8944 //                      rsurface.batchvertex3f_bufferoffset = 0;
8945                         {
8946                                 const float *v1, *v2;
8947                                 vec3_t start, end;
8948                                 float f, l;
8949                                 struct
8950                                 {
8951                                         float length2;
8952                                         const float *v1;
8953                                         const float *v2;
8954                                 }
8955                                 shortest[2];
8956                                 memset(shortest, 0, sizeof(shortest));
8957                                 // a single autosprite surface can contain multiple sprites...
8958                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8959                                 {
8960                                         VectorClear(center);
8961                                         for (i = 0;i < 4;i++)
8962                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8963                                         VectorScale(center, 0.25f, center);
8964                                         // find the two shortest edges, then use them to define the
8965                                         // axis vectors for rotating around the central axis
8966                                         for (i = 0;i < 6;i++)
8967                                         {
8968                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8969                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8970                                                 l = VectorDistance2(v1, v2);
8971                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8972                                                 if (v1[2] != v2[2])
8973                                                         l += (1.0f / 1024.0f);
8974                                                 if (shortest[0].length2 > l || i == 0)
8975                                                 {
8976                                                         shortest[1] = shortest[0];
8977                                                         shortest[0].length2 = l;
8978                                                         shortest[0].v1 = v1;
8979                                                         shortest[0].v2 = v2;
8980                                                 }
8981                                                 else if (shortest[1].length2 > l || i == 1)
8982                                                 {
8983                                                         shortest[1].length2 = l;
8984                                                         shortest[1].v1 = v1;
8985                                                         shortest[1].v2 = v2;
8986                                                 }
8987                                         }
8988                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8989                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8990                                         // this calculates the right vector from the shortest edge
8991                                         // and the up vector from the edge midpoints
8992                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8993                                         VectorNormalize(right);
8994                                         VectorSubtract(end, start, up);
8995                                         VectorNormalize(up);
8996                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8997                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8998                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8999                                         VectorNegate(forward, forward);
9000                                         VectorReflect(forward, 0, up, forward);
9001                                         VectorNormalize(forward);
9002                                         CrossProduct(up, forward, newright);
9003                                         VectorNormalize(newright);
9004                                         // rotate the quad around the up axis vector, this is made
9005                                         // especially easy by the fact we know the quad is flat,
9006                                         // so we only have to subtract the center position and
9007                                         // measure distance along the right vector, and then
9008                                         // multiply that by the newright vector and add back the
9009                                         // center position
9010                                         // we also need to subtract the old position to undo the
9011                                         // displacement from the center, which we do with a
9012                                         // DotProduct, the subtraction/addition of center is also
9013                                         // optimized into DotProducts here
9014                                         l = DotProduct(right, center);
9015                                         for (i = 0;i < 4;i++)
9016                                         {
9017                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9018                                                 f = DotProduct(right, v1) - l;
9019                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9020                                         }
9021                                 }
9022                         }
9023                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9024                         {
9025 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9026 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9027 //                              rsurface.batchnormal3f_bufferoffset = 0;
9028                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9029                         }
9030                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9031                         {
9032 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9033 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9034 //                              rsurface.batchsvector3f_bufferoffset = 0;
9035 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9036 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9037 //                              rsurface.batchtvector3f_bufferoffset = 0;
9038                                 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);
9039                         }
9040                         break;
9041                 case Q3DEFORM_NORMAL:
9042                         // deform the normals to make reflections wavey
9043                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9044                         rsurface.batchnormal3f_vertexbuffer = NULL;
9045                         rsurface.batchnormal3f_bufferoffset = 0;
9046                         for (j = 0;j < batchnumvertices;j++)
9047                         {
9048                                 float vertex[3];
9049                                 float *normal = rsurface.batchnormal3f + 3*j;
9050                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9051                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9052                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9053                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9054                                 VectorNormalize(normal);
9055                         }
9056                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9057                         {
9058 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9059 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9060 //                              rsurface.batchsvector3f_bufferoffset = 0;
9061 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9062 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9063 //                              rsurface.batchtvector3f_bufferoffset = 0;
9064                                 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);
9065                         }
9066                         break;
9067                 case Q3DEFORM_WAVE:
9068                         // deform vertex array to make wavey water and flags and such
9069                         waveparms[0] = deform->waveparms[0];
9070                         waveparms[1] = deform->waveparms[1];
9071                         waveparms[2] = deform->waveparms[2];
9072                         waveparms[3] = deform->waveparms[3];
9073                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9074                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9075                         // this is how a divisor of vertex influence on deformation
9076                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9077                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9078 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9079 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9080 //                      rsurface.batchvertex3f_bufferoffset = 0;
9081 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9082 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9083 //                      rsurface.batchnormal3f_bufferoffset = 0;
9084                         for (j = 0;j < batchnumvertices;j++)
9085                         {
9086                                 // if the wavefunc depends on time, evaluate it per-vertex
9087                                 if (waveparms[3])
9088                                 {
9089                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9090                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9091                                 }
9092                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9093                         }
9094                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9095                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9096                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9097                         {
9098 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9099 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9100 //                              rsurface.batchsvector3f_bufferoffset = 0;
9101 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9102 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9103 //                              rsurface.batchtvector3f_bufferoffset = 0;
9104                                 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);
9105                         }
9106                         break;
9107                 case Q3DEFORM_BULGE:
9108                         // deform vertex array to make the surface have moving bulges
9109 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9110 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9111 //                      rsurface.batchvertex3f_bufferoffset = 0;
9112 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9113 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9114 //                      rsurface.batchnormal3f_bufferoffset = 0;
9115                         for (j = 0;j < batchnumvertices;j++)
9116                         {
9117                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9118                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9119                         }
9120                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9121                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9122                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9123                         {
9124 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9125 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9126 //                              rsurface.batchsvector3f_bufferoffset = 0;
9127 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9128 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9129 //                              rsurface.batchtvector3f_bufferoffset = 0;
9130                                 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);
9131                         }
9132                         break;
9133                 case Q3DEFORM_MOVE:
9134                         // deform vertex array
9135                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9136                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9137                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9138                         VectorScale(deform->parms, scale, waveparms);
9139 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9140 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9141 //                      rsurface.batchvertex3f_bufferoffset = 0;
9142                         for (j = 0;j < batchnumvertices;j++)
9143                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9144                         break;
9145                 }
9146         }
9147
9148         // generate texcoords based on the chosen texcoord source
9149         switch(rsurface.texture->tcgen.tcgen)
9150         {
9151         default:
9152         case Q3TCGEN_TEXTURE:
9153                 break;
9154         case Q3TCGEN_LIGHTMAP:
9155 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9156 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9157 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9158                 if (rsurface.batchtexcoordlightmap2f)
9159                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9160                 break;
9161         case Q3TCGEN_VECTOR:
9162 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9163 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9164 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9165                 for (j = 0;j < batchnumvertices;j++)
9166                 {
9167                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9168                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9169                 }
9170                 break;
9171         case Q3TCGEN_ENVIRONMENT:
9172                 // make environment reflections using a spheremap
9173                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9174                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9175                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9176                 for (j = 0;j < batchnumvertices;j++)
9177                 {
9178                         // identical to Q3A's method, but executed in worldspace so
9179                         // carried models can be shiny too
9180
9181                         float viewer[3], d, reflected[3], worldreflected[3];
9182
9183                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9184                         // VectorNormalize(viewer);
9185
9186                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9187
9188                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9189                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9190                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9191                         // note: this is proportinal to viewer, so we can normalize later
9192
9193                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9194                         VectorNormalize(worldreflected);
9195
9196                         // note: this sphere map only uses world x and z!
9197                         // so positive and negative y will LOOK THE SAME.
9198                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9199                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9200                 }
9201                 break;
9202         }
9203         // the only tcmod that needs software vertex processing is turbulent, so
9204         // check for it here and apply the changes if needed
9205         // and we only support that as the first one
9206         // (handling a mixture of turbulent and other tcmods would be problematic
9207         //  without punting it entirely to a software path)
9208         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9209         {
9210                 amplitude = rsurface.texture->tcmods[0].parms[1];
9211                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9212 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9213 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9214 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9215                 for (j = 0;j < batchnumvertices;j++)
9216                 {
9217                         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);
9218                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9219                 }
9220         }
9221
9222         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9223         {
9224                 // convert the modified arrays to vertex structs
9225 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9226 //              rsurface.batchvertexmeshbuffer = NULL;
9227                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9228                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9229                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9230                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9231                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9232                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9233                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9234                 {
9235                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9236                         {
9237                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9238                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9239                         }
9240                 }
9241                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9242                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9243                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9244                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9245                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9246                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9247                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9248                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9249                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9250         }
9251 }
9252
9253 void RSurf_DrawBatch(void)
9254 {
9255         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9256         // through the pipeline, killing it earlier in the pipeline would have
9257         // per-surface overhead rather than per-batch overhead, so it's best to
9258         // reject it here, before it hits glDraw.
9259         if (rsurface.batchnumtriangles == 0)
9260                 return;
9261 #if 0
9262         // batch debugging code
9263         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9264         {
9265                 int i;
9266                 int j;
9267                 int c;
9268                 const int *e;
9269                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9270                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9271                 {
9272                         c = e[i];
9273                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9274                         {
9275                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9276                                 {
9277                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9278                                                 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);
9279                                         break;
9280                                 }
9281                         }
9282                 }
9283         }
9284 #endif
9285         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);
9286 }
9287
9288 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9289 {
9290         // pick the closest matching water plane
9291         int planeindex, vertexindex, bestplaneindex = -1;
9292         float d, bestd;
9293         vec3_t vert;
9294         const float *v;
9295         r_waterstate_waterplane_t *p;
9296         qboolean prepared = false;
9297         bestd = 0;
9298         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9299         {
9300                 if(p->camera_entity != rsurface.texture->camera_entity)
9301                         continue;
9302                 d = 0;
9303                 if(!prepared)
9304                 {
9305                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9306                         prepared = true;
9307                         if(rsurface.batchnumvertices == 0)
9308                                 break;
9309                 }
9310                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9311                 {
9312                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9313                         d += fabs(PlaneDiff(vert, &p->plane));
9314                 }
9315                 if (bestd > d || bestplaneindex < 0)
9316                 {
9317                         bestd = d;
9318                         bestplaneindex = planeindex;
9319                 }
9320         }
9321         return bestplaneindex;
9322         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9323         // this situation though, as it might be better to render single larger
9324         // batches with useless stuff (backface culled for example) than to
9325         // render multiple smaller batches
9326 }
9327
9328 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9329 {
9330         int i;
9331         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9332         rsurface.passcolor4f_vertexbuffer = 0;
9333         rsurface.passcolor4f_bufferoffset = 0;
9334         for (i = 0;i < rsurface.batchnumvertices;i++)
9335                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9336 }
9337
9338 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9339 {
9340         int i;
9341         float f;
9342         const float *v;
9343         const float *c;
9344         float *c2;
9345         if (rsurface.passcolor4f)
9346         {
9347                 // generate color arrays
9348                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9349                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9350                 rsurface.passcolor4f_vertexbuffer = 0;
9351                 rsurface.passcolor4f_bufferoffset = 0;
9352                 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)
9353                 {
9354                         f = RSurf_FogVertex(v);
9355                         c2[0] = c[0] * f;
9356                         c2[1] = c[1] * f;
9357                         c2[2] = c[2] * f;
9358                         c2[3] = c[3];
9359                 }
9360         }
9361         else
9362         {
9363                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9364                 rsurface.passcolor4f_vertexbuffer = 0;
9365                 rsurface.passcolor4f_bufferoffset = 0;
9366                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9367                 {
9368                         f = RSurf_FogVertex(v);
9369                         c2[0] = f;
9370                         c2[1] = f;
9371                         c2[2] = f;
9372                         c2[3] = 1;
9373                 }
9374         }
9375 }
9376
9377 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9378 {
9379         int i;
9380         float f;
9381         const float *v;
9382         const float *c;
9383         float *c2;
9384         if (!rsurface.passcolor4f)
9385                 return;
9386         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9387         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9388         rsurface.passcolor4f_vertexbuffer = 0;
9389         rsurface.passcolor4f_bufferoffset = 0;
9390         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)
9391         {
9392                 f = RSurf_FogVertex(v);
9393                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9394                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9395                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9396                 c2[3] = c[3];
9397         }
9398 }
9399
9400 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9401 {
9402         int i;
9403         const float *c;
9404         float *c2;
9405         if (!rsurface.passcolor4f)
9406                 return;
9407         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9408         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9409         rsurface.passcolor4f_vertexbuffer = 0;
9410         rsurface.passcolor4f_bufferoffset = 0;
9411         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9412         {
9413                 c2[0] = c[0] * r;
9414                 c2[1] = c[1] * g;
9415                 c2[2] = c[2] * b;
9416                 c2[3] = c[3] * a;
9417         }
9418 }
9419
9420 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9421 {
9422         int i;
9423         const float *c;
9424         float *c2;
9425         if (!rsurface.passcolor4f)
9426                 return;
9427         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9428         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9429         rsurface.passcolor4f_vertexbuffer = 0;
9430         rsurface.passcolor4f_bufferoffset = 0;
9431         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9432         {
9433                 c2[0] = c[0] + r_refdef.scene.ambient;
9434                 c2[1] = c[1] + r_refdef.scene.ambient;
9435                 c2[2] = c[2] + r_refdef.scene.ambient;
9436                 c2[3] = c[3];
9437         }
9438 }
9439
9440 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9441 {
9442         // TODO: optimize
9443         rsurface.passcolor4f = NULL;
9444         rsurface.passcolor4f_vertexbuffer = 0;
9445         rsurface.passcolor4f_bufferoffset = 0;
9446         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9447         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9448         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9449         GL_Color(r, g, b, a);
9450         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9451         RSurf_DrawBatch();
9452 }
9453
9454 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9455 {
9456         // TODO: optimize applyfog && applycolor case
9457         // just apply fog if necessary, and tint the fog color array if necessary
9458         rsurface.passcolor4f = NULL;
9459         rsurface.passcolor4f_vertexbuffer = 0;
9460         rsurface.passcolor4f_bufferoffset = 0;
9461         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9462         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9463         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9464         GL_Color(r, g, b, a);
9465         RSurf_DrawBatch();
9466 }
9467
9468 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9469 {
9470         // TODO: optimize
9471         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9472         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9473         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9474         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9475         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9476         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9477         GL_Color(r, g, b, a);
9478         RSurf_DrawBatch();
9479 }
9480
9481 static void RSurf_DrawBatch_GL11_ClampColor(void)
9482 {
9483         int i;
9484         const float *c1;
9485         float *c2;
9486         if (!rsurface.passcolor4f)
9487                 return;
9488         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9489         {
9490                 c2[0] = bound(0.0f, c1[0], 1.0f);
9491                 c2[1] = bound(0.0f, c1[1], 1.0f);
9492                 c2[2] = bound(0.0f, c1[2], 1.0f);
9493                 c2[3] = bound(0.0f, c1[3], 1.0f);
9494         }
9495 }
9496
9497 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9498 {
9499         int i;
9500         float f;
9501         const float *v;
9502         const float *n;
9503         float *c;
9504         //vec3_t eyedir;
9505
9506         // fake shading
9507         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9508         rsurface.passcolor4f_vertexbuffer = 0;
9509         rsurface.passcolor4f_bufferoffset = 0;
9510         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)
9511         {
9512                 f = -DotProduct(r_refdef.view.forward, n);
9513                 f = max(0, f);
9514                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9515                 f *= r_refdef.lightmapintensity;
9516                 Vector4Set(c, f, f, f, 1);
9517         }
9518 }
9519
9520 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9521 {
9522         RSurf_DrawBatch_GL11_ApplyFakeLight();
9523         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9524         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9525         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9526         GL_Color(r, g, b, a);
9527         RSurf_DrawBatch();
9528 }
9529
9530 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9531 {
9532         int i;
9533         float f;
9534         float alpha;
9535         const float *v;
9536         const float *n;
9537         float *c;
9538         vec3_t ambientcolor;
9539         vec3_t diffusecolor;
9540         vec3_t lightdir;
9541         // TODO: optimize
9542         // model lighting
9543         VectorCopy(rsurface.modellight_lightdir, lightdir);
9544         f = 0.5f * r_refdef.lightmapintensity;
9545         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9546         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9547         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9548         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9549         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9550         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9551         alpha = *a;
9552         if (VectorLength2(diffusecolor) > 0)
9553         {
9554                 // q3-style directional shading
9555                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9556                 rsurface.passcolor4f_vertexbuffer = 0;
9557                 rsurface.passcolor4f_bufferoffset = 0;
9558                 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)
9559                 {
9560                         if ((f = DotProduct(n, lightdir)) > 0)
9561                                 VectorMA(ambientcolor, f, diffusecolor, c);
9562                         else
9563                                 VectorCopy(ambientcolor, c);
9564                         c[3] = alpha;
9565                 }
9566                 *r = 1;
9567                 *g = 1;
9568                 *b = 1;
9569                 *a = 1;
9570                 *applycolor = false;
9571         }
9572         else
9573         {
9574                 *r = ambientcolor[0];
9575                 *g = ambientcolor[1];
9576                 *b = ambientcolor[2];
9577                 rsurface.passcolor4f = NULL;
9578                 rsurface.passcolor4f_vertexbuffer = 0;
9579                 rsurface.passcolor4f_bufferoffset = 0;
9580         }
9581 }
9582
9583 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9584 {
9585         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9586         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9587         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9588         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9589         GL_Color(r, g, b, a);
9590         RSurf_DrawBatch();
9591 }
9592
9593 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9594 {
9595         int i;
9596         float f;
9597         const float *v;
9598         float *c;
9599
9600         // fake shading
9601         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9602         rsurface.passcolor4f_vertexbuffer = 0;
9603         rsurface.passcolor4f_bufferoffset = 0;
9604
9605         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9606         {
9607                 f = 1 - RSurf_FogVertex(v);
9608                 c[0] = r;
9609                 c[1] = g;
9610                 c[2] = b;
9611                 c[3] = f * a;
9612         }
9613 }
9614
9615 void RSurf_SetupDepthAndCulling(void)
9616 {
9617         // submodels are biased to avoid z-fighting with world surfaces that they
9618         // may be exactly overlapping (avoids z-fighting artifacts on certain
9619         // doors and things in Quake maps)
9620         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9621         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9622         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9623         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9624 }
9625
9626 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9627 {
9628         // transparent sky would be ridiculous
9629         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9630                 return;
9631         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9632         skyrenderlater = true;
9633         RSurf_SetupDepthAndCulling();
9634         GL_DepthMask(true);
9635         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9636         // skymasking on them, and Quake3 never did sky masking (unlike
9637         // software Quake and software Quake2), so disable the sky masking
9638         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9639         // and skymasking also looks very bad when noclipping outside the
9640         // level, so don't use it then either.
9641         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9642         {
9643                 R_Mesh_ResetTextureState();
9644                 if (skyrendermasked)
9645                 {
9646                         R_SetupShader_DepthOrShadow(false);
9647                         // depth-only (masking)
9648                         GL_ColorMask(0,0,0,0);
9649                         // just to make sure that braindead drivers don't draw
9650                         // anything despite that colormask...
9651                         GL_BlendFunc(GL_ZERO, GL_ONE);
9652                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9653                         if (rsurface.batchvertex3fbuffer)
9654                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9655                         else
9656                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9657                 }
9658                 else
9659                 {
9660                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9661                         // fog sky
9662                         GL_BlendFunc(GL_ONE, GL_ZERO);
9663                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9664                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9665                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9666                 }
9667                 RSurf_DrawBatch();
9668                 if (skyrendermasked)
9669                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9670         }
9671         R_Mesh_ResetTextureState();
9672         GL_Color(1, 1, 1, 1);
9673 }
9674
9675 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9676 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9677 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9678 {
9679         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9680                 return;
9681         if (prepass)
9682         {
9683                 // render screenspace normalmap to texture
9684                 GL_DepthMask(true);
9685                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9686                 RSurf_DrawBatch();
9687         }
9688
9689         // bind lightmap texture
9690
9691         // water/refraction/reflection/camera surfaces have to be handled specially
9692         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9693         {
9694                 int start, end, startplaneindex;
9695                 for (start = 0;start < texturenumsurfaces;start = end)
9696                 {
9697                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9698                         if(startplaneindex < 0)
9699                         {
9700                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9701                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9702                                 end = start + 1;
9703                                 continue;
9704                         }
9705                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9706                                 ;
9707                         // now that we have a batch using the same planeindex, render it
9708                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9709                         {
9710                                 // render water or distortion background
9711                                 GL_DepthMask(true);
9712                                 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), false);
9713                                 RSurf_DrawBatch();
9714                                 // blend surface on top
9715                                 GL_DepthMask(false);
9716                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9717                                 RSurf_DrawBatch();
9718                         }
9719                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9720                         {
9721                                 // render surface with reflection texture as input
9722                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9723                                 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), false);
9724                                 RSurf_DrawBatch();
9725                         }
9726                 }
9727                 return;
9728         }
9729
9730         // render surface batch normally
9731         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9732         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
9733         RSurf_DrawBatch();
9734 }
9735
9736 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9737 {
9738         // OpenGL 1.3 path - anything not completely ancient
9739         qboolean applycolor;
9740         qboolean applyfog;
9741         int layerindex;
9742         const texturelayer_t *layer;
9743         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);
9744         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9745
9746         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9747         {
9748                 vec4_t layercolor;
9749                 int layertexrgbscale;
9750                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9751                 {
9752                         if (layerindex == 0)
9753                                 GL_AlphaTest(true);
9754                         else
9755                         {
9756                                 GL_AlphaTest(false);
9757                                 GL_DepthFunc(GL_EQUAL);
9758                         }
9759                 }
9760                 GL_DepthMask(layer->depthmask && writedepth);
9761                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9762                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9763                 {
9764                         layertexrgbscale = 4;
9765                         VectorScale(layer->color, 0.25f, layercolor);
9766                 }
9767                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9768                 {
9769                         layertexrgbscale = 2;
9770                         VectorScale(layer->color, 0.5f, layercolor);
9771                 }
9772                 else
9773                 {
9774                         layertexrgbscale = 1;
9775                         VectorScale(layer->color, 1.0f, layercolor);
9776                 }
9777                 layercolor[3] = layer->color[3];
9778                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9779                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9780                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9781                 switch (layer->type)
9782                 {
9783                 case TEXTURELAYERTYPE_LITTEXTURE:
9784                         // single-pass lightmapped texture with 2x rgbscale
9785                         R_Mesh_TexBind(0, r_texture_white);
9786                         R_Mesh_TexMatrix(0, NULL);
9787                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9788                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9789                         R_Mesh_TexBind(1, layer->texture);
9790                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9791                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9792                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9793                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9794                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9795                         else if (FAKELIGHT_ENABLED)
9796                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9797                         else if (rsurface.uselightmaptexture)
9798                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9799                         else
9800                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9801                         break;
9802                 case TEXTURELAYERTYPE_TEXTURE:
9803                         // singletexture unlit texture with transparency support
9804                         R_Mesh_TexBind(0, layer->texture);
9805                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9806                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9807                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9808                         R_Mesh_TexBind(1, 0);
9809                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9810                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9811                         break;
9812                 case TEXTURELAYERTYPE_FOG:
9813                         // singletexture fogging
9814                         if (layer->texture)
9815                         {
9816                                 R_Mesh_TexBind(0, layer->texture);
9817                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9818                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9819                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9820                         }
9821                         else
9822                         {
9823                                 R_Mesh_TexBind(0, 0);
9824                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9825                         }
9826                         R_Mesh_TexBind(1, 0);
9827                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9828                         // generate a color array for the fog pass
9829                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9830                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9831                         RSurf_DrawBatch();
9832                         break;
9833                 default:
9834                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9835                 }
9836         }
9837         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9838         {
9839                 GL_DepthFunc(GL_LEQUAL);
9840                 GL_AlphaTest(false);
9841         }
9842 }
9843
9844 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9845 {
9846         // OpenGL 1.1 - crusty old voodoo path
9847         qboolean applyfog;
9848         int layerindex;
9849         const texturelayer_t *layer;
9850         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);
9851         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9852
9853         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9854         {
9855                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9856                 {
9857                         if (layerindex == 0)
9858                                 GL_AlphaTest(true);
9859                         else
9860                         {
9861                                 GL_AlphaTest(false);
9862                                 GL_DepthFunc(GL_EQUAL);
9863                         }
9864                 }
9865                 GL_DepthMask(layer->depthmask && writedepth);
9866                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9867                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9868                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9869                 switch (layer->type)
9870                 {
9871                 case TEXTURELAYERTYPE_LITTEXTURE:
9872                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9873                         {
9874                                 // two-pass lit texture with 2x rgbscale
9875                                 // first the lightmap pass
9876                                 R_Mesh_TexBind(0, r_texture_white);
9877                                 R_Mesh_TexMatrix(0, NULL);
9878                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9879                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9880                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9881                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9882                                 else if (FAKELIGHT_ENABLED)
9883                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9884                                 else if (rsurface.uselightmaptexture)
9885                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9886                                 else
9887                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9888                                 // then apply the texture to it
9889                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9890                                 R_Mesh_TexBind(0, layer->texture);
9891                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9892                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9893                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9894                                 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);
9895                         }
9896                         else
9897                         {
9898                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9899                                 R_Mesh_TexBind(0, layer->texture);
9900                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9901                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9902                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9903                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9904                                         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);
9905                                 else
9906                                         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);
9907                         }
9908                         break;
9909                 case TEXTURELAYERTYPE_TEXTURE:
9910                         // singletexture unlit texture with transparency support
9911                         R_Mesh_TexBind(0, layer->texture);
9912                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9913                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9914                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9915                         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);
9916                         break;
9917                 case TEXTURELAYERTYPE_FOG:
9918                         // singletexture fogging
9919                         if (layer->texture)
9920                         {
9921                                 R_Mesh_TexBind(0, layer->texture);
9922                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9923                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9924                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9925                         }
9926                         else
9927                         {
9928                                 R_Mesh_TexBind(0, 0);
9929                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9930                         }
9931                         // generate a color array for the fog pass
9932                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9933                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9934                         RSurf_DrawBatch();
9935                         break;
9936                 default:
9937                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9938                 }
9939         }
9940         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9941         {
9942                 GL_DepthFunc(GL_LEQUAL);
9943                 GL_AlphaTest(false);
9944         }
9945 }
9946
9947 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9948 {
9949         int vi;
9950         int j;
9951         r_vertexgeneric_t *batchvertex;
9952         float c[4];
9953
9954 //      R_Mesh_ResetTextureState();
9955         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9956
9957         if(rsurface.texture && rsurface.texture->currentskinframe)
9958         {
9959                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9960                 c[3] *= rsurface.texture->currentalpha;
9961         }
9962         else
9963         {
9964                 c[0] = 1;
9965                 c[1] = 0;
9966                 c[2] = 1;
9967                 c[3] = 1;
9968         }
9969
9970         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9971         {
9972                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9973                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9974                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9975         }
9976
9977         // brighten it up (as texture value 127 means "unlit")
9978         c[0] *= 2 * r_refdef.view.colorscale;
9979         c[1] *= 2 * r_refdef.view.colorscale;
9980         c[2] *= 2 * r_refdef.view.colorscale;
9981
9982         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9983                 c[3] *= r_wateralpha.value;
9984
9985         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9986         {
9987                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9988                 GL_DepthMask(false);
9989         }
9990         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9991         {
9992                 GL_BlendFunc(GL_ONE, GL_ONE);
9993                 GL_DepthMask(false);
9994         }
9995         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9996         {
9997                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9998                 GL_DepthMask(false);
9999         }
10000         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10001         {
10002                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10003                 GL_DepthMask(false);
10004         }
10005         else
10006         {
10007                 GL_BlendFunc(GL_ONE, GL_ZERO);
10008                 GL_DepthMask(writedepth);
10009         }
10010
10011         if (r_showsurfaces.integer == 3)
10012         {
10013                 rsurface.passcolor4f = NULL;
10014
10015                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10016                 {
10017                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10018
10019                         rsurface.passcolor4f = NULL;
10020                         rsurface.passcolor4f_vertexbuffer = 0;
10021                         rsurface.passcolor4f_bufferoffset = 0;
10022                 }
10023                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10024                 {
10025                         qboolean applycolor = true;
10026                         float one = 1.0;
10027
10028                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10029
10030                         r_refdef.lightmapintensity = 1;
10031                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10032                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10033                 }
10034                 else if (FAKELIGHT_ENABLED)
10035                 {
10036                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10037
10038                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10039                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10040                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10041                 }
10042                 else
10043                 {
10044                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10045
10046                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10047                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10048                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10049                 }
10050
10051                 if(!rsurface.passcolor4f)
10052                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10053
10054                 RSurf_DrawBatch_GL11_ApplyAmbient();
10055                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10056                 if(r_refdef.fogenabled)
10057                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10058                 RSurf_DrawBatch_GL11_ClampColor();
10059
10060                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10061                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10062                 RSurf_DrawBatch();
10063         }
10064         else if (!r_refdef.view.showdebug)
10065         {
10066                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10067                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10068                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10069                 {
10070                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10071                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10072                 }
10073                 R_Mesh_PrepareVertices_Generic_Unlock();
10074                 RSurf_DrawBatch();
10075         }
10076         else if (r_showsurfaces.integer == 4)
10077         {
10078                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10079                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10080                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10081                 {
10082                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10083                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10084                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10085                 }
10086                 R_Mesh_PrepareVertices_Generic_Unlock();
10087                 RSurf_DrawBatch();
10088         }
10089         else if (r_showsurfaces.integer == 2)
10090         {
10091                 const int *e;
10092                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10093                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10094                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10095                 {
10096                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10097                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10098                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10099                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10100                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10101                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10102                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10103                 }
10104                 R_Mesh_PrepareVertices_Generic_Unlock();
10105                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10106         }
10107         else
10108         {
10109                 int texturesurfaceindex;
10110                 int k;
10111                 const msurface_t *surface;
10112                 float surfacecolor4f[4];
10113                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10114                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10115                 vi = 0;
10116                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10117                 {
10118                         surface = texturesurfacelist[texturesurfaceindex];
10119                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10120                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10121                         for (j = 0;j < surface->num_vertices;j++)
10122                         {
10123                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10124                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10125                                 vi++;
10126                         }
10127                 }
10128                 R_Mesh_PrepareVertices_Generic_Unlock();
10129                 RSurf_DrawBatch();
10130         }
10131 }
10132
10133 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10134 {
10135         CHECKGLERROR
10136         RSurf_SetupDepthAndCulling();
10137         if (r_showsurfaces.integer)
10138         {
10139                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10140                 return;
10141         }
10142         switch (vid.renderpath)
10143         {
10144         case RENDERPATH_GL20:
10145         case RENDERPATH_D3D9:
10146         case RENDERPATH_D3D10:
10147         case RENDERPATH_D3D11:
10148         case RENDERPATH_SOFT:
10149         case RENDERPATH_GLES2:
10150                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10151                 break;
10152         case RENDERPATH_GL13:
10153         case RENDERPATH_GLES1:
10154                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10155                 break;
10156         case RENDERPATH_GL11:
10157                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10158                 break;
10159         }
10160         CHECKGLERROR
10161 }
10162
10163 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10164 {
10165         CHECKGLERROR
10166         RSurf_SetupDepthAndCulling();
10167         if (r_showsurfaces.integer)
10168         {
10169                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10170                 return;
10171         }
10172         switch (vid.renderpath)
10173         {
10174         case RENDERPATH_GL20:
10175         case RENDERPATH_D3D9:
10176         case RENDERPATH_D3D10:
10177         case RENDERPATH_D3D11:
10178         case RENDERPATH_SOFT:
10179         case RENDERPATH_GLES2:
10180                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10181                 break;
10182         case RENDERPATH_GL13:
10183         case RENDERPATH_GLES1:
10184                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10185                 break;
10186         case RENDERPATH_GL11:
10187                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10188                 break;
10189         }
10190         CHECKGLERROR
10191 }
10192
10193 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10194 {
10195         int i, j;
10196         int texturenumsurfaces, endsurface;
10197         texture_t *texture;
10198         const msurface_t *surface;
10199         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10200
10201         // if the model is static it doesn't matter what value we give for
10202         // wantnormals and wanttangents, so this logic uses only rules applicable
10203         // to a model, knowing that they are meaningless otherwise
10204         if (ent == r_refdef.scene.worldentity)
10205                 RSurf_ActiveWorldEntity();
10206         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10207                 RSurf_ActiveModelEntity(ent, false, false, false);
10208         else
10209         {
10210                 switch (vid.renderpath)
10211                 {
10212                 case RENDERPATH_GL20:
10213                 case RENDERPATH_D3D9:
10214                 case RENDERPATH_D3D10:
10215                 case RENDERPATH_D3D11:
10216                 case RENDERPATH_SOFT:
10217                 case RENDERPATH_GLES2:
10218                         RSurf_ActiveModelEntity(ent, true, true, false);
10219                         break;
10220                 case RENDERPATH_GL11:
10221                 case RENDERPATH_GL13:
10222                 case RENDERPATH_GLES1:
10223                         RSurf_ActiveModelEntity(ent, true, false, false);
10224                         break;
10225                 }
10226         }
10227
10228         if (r_transparentdepthmasking.integer)
10229         {
10230                 qboolean setup = false;
10231                 for (i = 0;i < numsurfaces;i = j)
10232                 {
10233                         j = i + 1;
10234                         surface = rsurface.modelsurfaces + surfacelist[i];
10235                         texture = surface->texture;
10236                         rsurface.texture = R_GetCurrentTexture(texture);
10237                         rsurface.lightmaptexture = NULL;
10238                         rsurface.deluxemaptexture = NULL;
10239                         rsurface.uselightmaptexture = false;
10240                         // scan ahead until we find a different texture
10241                         endsurface = min(i + 1024, numsurfaces);
10242                         texturenumsurfaces = 0;
10243                         texturesurfacelist[texturenumsurfaces++] = surface;
10244                         for (;j < endsurface;j++)
10245                         {
10246                                 surface = rsurface.modelsurfaces + surfacelist[j];
10247                                 if (texture != surface->texture)
10248                                         break;
10249                                 texturesurfacelist[texturenumsurfaces++] = surface;
10250                         }
10251                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10252                                 continue;
10253                         // render the range of surfaces as depth
10254                         if (!setup)
10255                         {
10256                                 setup = true;
10257                                 GL_ColorMask(0,0,0,0);
10258                                 GL_Color(1,1,1,1);
10259                                 GL_DepthTest(true);
10260                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10261                                 GL_DepthMask(true);
10262 //                              R_Mesh_ResetTextureState();
10263                                 R_SetupShader_DepthOrShadow(false);
10264                         }
10265                         RSurf_SetupDepthAndCulling();
10266                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10267                         if (rsurface.batchvertex3fbuffer)
10268                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10269                         else
10270                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10271                         RSurf_DrawBatch();
10272                 }
10273                 if (setup)
10274                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10275         }
10276
10277         for (i = 0;i < numsurfaces;i = j)
10278         {
10279                 j = i + 1;
10280                 surface = rsurface.modelsurfaces + surfacelist[i];
10281                 texture = surface->texture;
10282                 rsurface.texture = R_GetCurrentTexture(texture);
10283                 // scan ahead until we find a different texture
10284                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10285                 texturenumsurfaces = 0;
10286                 texturesurfacelist[texturenumsurfaces++] = surface;
10287                 if(FAKELIGHT_ENABLED)
10288                 {
10289                         rsurface.lightmaptexture = NULL;
10290                         rsurface.deluxemaptexture = NULL;
10291                         rsurface.uselightmaptexture = false;
10292                         for (;j < endsurface;j++)
10293                         {
10294                                 surface = rsurface.modelsurfaces + surfacelist[j];
10295                                 if (texture != surface->texture)
10296                                         break;
10297                                 texturesurfacelist[texturenumsurfaces++] = surface;
10298                         }
10299                 }
10300                 else
10301                 {
10302                         rsurface.lightmaptexture = surface->lightmaptexture;
10303                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10304                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10305                         for (;j < endsurface;j++)
10306                         {
10307                                 surface = rsurface.modelsurfaces + surfacelist[j];
10308                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10309                                         break;
10310                                 texturesurfacelist[texturenumsurfaces++] = surface;
10311                         }
10312                 }
10313                 // render the range of surfaces
10314                 if (ent == r_refdef.scene.worldentity)
10315                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10316                 else
10317                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10318         }
10319         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10320 }
10321
10322 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10323 {
10324         // transparent surfaces get pushed off into the transparent queue
10325         int surfacelistindex;
10326         const msurface_t *surface;
10327         vec3_t tempcenter, center;
10328         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10329         {
10330                 surface = texturesurfacelist[surfacelistindex];
10331                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10332                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10333                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10334                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10335                 if (queueentity->transparent_offset) // transparent offset
10336                 {
10337                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10338                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10339                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10340                 }
10341                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10342         }
10343 }
10344
10345 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10346 {
10347         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10348                 return;
10349         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10350                 return;
10351         RSurf_SetupDepthAndCulling();
10352         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10353         if (rsurface.batchvertex3fbuffer)
10354                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10355         else
10356                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10357         RSurf_DrawBatch();
10358 }
10359
10360 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10361 {
10362         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10363         CHECKGLERROR
10364         if (depthonly)
10365                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10366         else if (prepass)
10367         {
10368                 if (!rsurface.texture->currentnumlayers)
10369                         return;
10370                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10371                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10372                 else
10373                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10374         }
10375         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10376                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10377         else if (!rsurface.texture->currentnumlayers)
10378                 return;
10379         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10380         {
10381                 // in the deferred case, transparent surfaces were queued during prepass
10382                 if (!r_shadow_usingdeferredprepass)
10383                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10384         }
10385         else
10386         {
10387                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10388                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10389         }
10390         CHECKGLERROR
10391 }
10392
10393 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10394 {
10395         int i, j;
10396         texture_t *texture;
10397         R_FrameData_SetMark();
10398         // break the surface list down into batches by texture and use of lightmapping
10399         for (i = 0;i < numsurfaces;i = j)
10400         {
10401                 j = i + 1;
10402                 // texture is the base texture pointer, rsurface.texture is the
10403                 // current frame/skin the texture is directing us to use (for example
10404                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10405                 // use skin 1 instead)
10406                 texture = surfacelist[i]->texture;
10407                 rsurface.texture = R_GetCurrentTexture(texture);
10408                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10409                 {
10410                         // if this texture is not the kind we want, skip ahead to the next one
10411                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10412                                 ;
10413                         continue;
10414                 }
10415                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10416                 {
10417                         rsurface.lightmaptexture = NULL;
10418                         rsurface.deluxemaptexture = NULL;
10419                         rsurface.uselightmaptexture = false;
10420                         // simply scan ahead until we find a different texture or lightmap state
10421                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10422                                 ;
10423                 }
10424                 else
10425                 {
10426                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10427                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10428                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10429                         // simply scan ahead until we find a different texture or lightmap state
10430                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10431                                 ;
10432                 }
10433                 // render the range of surfaces
10434                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10435         }
10436         R_FrameData_ReturnToMark();
10437 }
10438
10439 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10440 {
10441         CHECKGLERROR
10442         if (depthonly)
10443                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10444         else if (prepass)
10445         {
10446                 if (!rsurface.texture->currentnumlayers)
10447                         return;
10448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10449                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10450                 else
10451                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10452         }
10453         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10454                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10455         else if (!rsurface.texture->currentnumlayers)
10456                 return;
10457         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10458         {
10459                 // in the deferred case, transparent surfaces were queued during prepass
10460                 if (!r_shadow_usingdeferredprepass)
10461                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10462         }
10463         else
10464         {
10465                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10466                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10467         }
10468         CHECKGLERROR
10469 }
10470
10471 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10472 {
10473         int i, j;
10474         texture_t *texture;
10475         R_FrameData_SetMark();
10476         // break the surface list down into batches by texture and use of lightmapping
10477         for (i = 0;i < numsurfaces;i = j)
10478         {
10479                 j = i + 1;
10480                 // texture is the base texture pointer, rsurface.texture is the
10481                 // current frame/skin the texture is directing us to use (for example
10482                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10483                 // use skin 1 instead)
10484                 texture = surfacelist[i]->texture;
10485                 rsurface.texture = R_GetCurrentTexture(texture);
10486                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10487                 {
10488                         // if this texture is not the kind we want, skip ahead to the next one
10489                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10490                                 ;
10491                         continue;
10492                 }
10493                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10494                 {
10495                         rsurface.lightmaptexture = NULL;
10496                         rsurface.deluxemaptexture = NULL;
10497                         rsurface.uselightmaptexture = false;
10498                         // simply scan ahead until we find a different texture or lightmap state
10499                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10500                                 ;
10501                 }
10502                 else
10503                 {
10504                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10505                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10506                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10507                         // simply scan ahead until we find a different texture or lightmap state
10508                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10509                                 ;
10510                 }
10511                 // render the range of surfaces
10512                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10513         }
10514         R_FrameData_ReturnToMark();
10515 }
10516
10517 float locboxvertex3f[6*4*3] =
10518 {
10519         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10520         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10521         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10522         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10523         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10524         1,0,0, 0,0,0, 0,1,0, 1,1,0
10525 };
10526
10527 unsigned short locboxelements[6*2*3] =
10528 {
10529          0, 1, 2, 0, 2, 3,
10530          4, 5, 6, 4, 6, 7,
10531          8, 9,10, 8,10,11,
10532         12,13,14, 12,14,15,
10533         16,17,18, 16,18,19,
10534         20,21,22, 20,22,23
10535 };
10536
10537 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10538 {
10539         int i, j;
10540         cl_locnode_t *loc = (cl_locnode_t *)ent;
10541         vec3_t mins, size;
10542         float vertex3f[6*4*3];
10543         CHECKGLERROR
10544         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10545         GL_DepthMask(false);
10546         GL_DepthRange(0, 1);
10547         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10548         GL_DepthTest(true);
10549         GL_CullFace(GL_NONE);
10550         R_EntityMatrix(&identitymatrix);
10551
10552 //      R_Mesh_ResetTextureState();
10553
10554         i = surfacelist[0];
10555         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10556                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10557                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10558                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10559
10560         if (VectorCompare(loc->mins, loc->maxs))
10561         {
10562                 VectorSet(size, 2, 2, 2);
10563                 VectorMA(loc->mins, -0.5f, size, mins);
10564         }
10565         else
10566         {
10567                 VectorCopy(loc->mins, mins);
10568                 VectorSubtract(loc->maxs, loc->mins, size);
10569         }
10570
10571         for (i = 0;i < 6*4*3;)
10572                 for (j = 0;j < 3;j++, i++)
10573                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10574
10575         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10576         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10577         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10578 }
10579
10580 void R_DrawLocs(void)
10581 {
10582         int index;
10583         cl_locnode_t *loc, *nearestloc;
10584         vec3_t center;
10585         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10586         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10587         {
10588                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10589                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10590         }
10591 }
10592
10593 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10594 {
10595         if (decalsystem->decals)
10596                 Mem_Free(decalsystem->decals);
10597         memset(decalsystem, 0, sizeof(*decalsystem));
10598 }
10599
10600 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)
10601 {
10602         tridecal_t *decal;
10603         tridecal_t *decals;
10604         int i;
10605
10606         // expand or initialize the system
10607         if (decalsystem->maxdecals <= decalsystem->numdecals)
10608         {
10609                 decalsystem_t old = *decalsystem;
10610                 qboolean useshortelements;
10611                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10612                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10613                 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)));
10614                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10615                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10616                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10617                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10618                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10619                 if (decalsystem->numdecals)
10620                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10621                 if (old.decals)
10622                         Mem_Free(old.decals);
10623                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10624                         decalsystem->element3i[i] = i;
10625                 if (useshortelements)
10626                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10627                                 decalsystem->element3s[i] = i;
10628         }
10629
10630         // grab a decal and search for another free slot for the next one
10631         decals = decalsystem->decals;
10632         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10633         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10634                 ;
10635         decalsystem->freedecal = i;
10636         if (decalsystem->numdecals <= i)
10637                 decalsystem->numdecals = i + 1;
10638
10639         // initialize the decal
10640         decal->lived = 0;
10641         decal->triangleindex = triangleindex;
10642         decal->surfaceindex = surfaceindex;
10643         decal->decalsequence = decalsequence;
10644         decal->color4f[0][0] = c0[0];
10645         decal->color4f[0][1] = c0[1];
10646         decal->color4f[0][2] = c0[2];
10647         decal->color4f[0][3] = 1;
10648         decal->color4f[1][0] = c1[0];
10649         decal->color4f[1][1] = c1[1];
10650         decal->color4f[1][2] = c1[2];
10651         decal->color4f[1][3] = 1;
10652         decal->color4f[2][0] = c2[0];
10653         decal->color4f[2][1] = c2[1];
10654         decal->color4f[2][2] = c2[2];
10655         decal->color4f[2][3] = 1;
10656         decal->vertex3f[0][0] = v0[0];
10657         decal->vertex3f[0][1] = v0[1];
10658         decal->vertex3f[0][2] = v0[2];
10659         decal->vertex3f[1][0] = v1[0];
10660         decal->vertex3f[1][1] = v1[1];
10661         decal->vertex3f[1][2] = v1[2];
10662         decal->vertex3f[2][0] = v2[0];
10663         decal->vertex3f[2][1] = v2[1];
10664         decal->vertex3f[2][2] = v2[2];
10665         decal->texcoord2f[0][0] = t0[0];
10666         decal->texcoord2f[0][1] = t0[1];
10667         decal->texcoord2f[1][0] = t1[0];
10668         decal->texcoord2f[1][1] = t1[1];
10669         decal->texcoord2f[2][0] = t2[0];
10670         decal->texcoord2f[2][1] = t2[1];
10671         TriangleNormal(v0, v1, v2, decal->plane);
10672         VectorNormalize(decal->plane);
10673         decal->plane[3] = DotProduct(v0, decal->plane);
10674 }
10675
10676 extern cvar_t cl_decals_bias;
10677 extern cvar_t cl_decals_models;
10678 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10679 // baseparms, parms, temps
10680 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)
10681 {
10682         int cornerindex;
10683         int index;
10684         float v[9][3];
10685         const float *vertex3f;
10686         const float *normal3f;
10687         int numpoints;
10688         float points[2][9][3];
10689         float temp[3];
10690         float tc[9][2];
10691         float f;
10692         float c[9][4];
10693         const int *e;
10694
10695         e = rsurface.modelelement3i + 3*triangleindex;
10696
10697         vertex3f = rsurface.modelvertex3f;
10698         normal3f = rsurface.modelnormal3f;
10699
10700         if (normal3f)
10701         {
10702                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10703                 {
10704                         index = 3*e[cornerindex];
10705                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10706                 }
10707         }
10708         else
10709         {
10710                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10711                 {
10712                         index = 3*e[cornerindex];
10713                         VectorCopy(vertex3f + index, v[cornerindex]);
10714                 }
10715         }
10716
10717         // cull backfaces
10718         //TriangleNormal(v[0], v[1], v[2], normal);
10719         //if (DotProduct(normal, localnormal) < 0.0f)
10720         //      continue;
10721         // clip by each of the box planes formed from the projection matrix
10722         // if anything survives, we emit the decal
10723         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]);
10724         if (numpoints < 3)
10725                 return;
10726         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]);
10727         if (numpoints < 3)
10728                 return;
10729         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]);
10730         if (numpoints < 3)
10731                 return;
10732         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]);
10733         if (numpoints < 3)
10734                 return;
10735         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]);
10736         if (numpoints < 3)
10737                 return;
10738         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]);
10739         if (numpoints < 3)
10740                 return;
10741         // some part of the triangle survived, so we have to accept it...
10742         if (dynamic)
10743         {
10744                 // dynamic always uses the original triangle
10745                 numpoints = 3;
10746                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10747                 {
10748                         index = 3*e[cornerindex];
10749                         VectorCopy(vertex3f + index, v[cornerindex]);
10750                 }
10751         }
10752         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10753         {
10754                 // convert vertex positions to texcoords
10755                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10756                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10757                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10758                 // calculate distance fade from the projection origin
10759                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10760                 f = bound(0.0f, f, 1.0f);
10761                 c[cornerindex][0] = r * f;
10762                 c[cornerindex][1] = g * f;
10763                 c[cornerindex][2] = b * f;
10764                 c[cornerindex][3] = 1.0f;
10765                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10766         }
10767         if (dynamic)
10768                 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);
10769         else
10770                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10771                         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);
10772 }
10773 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)
10774 {
10775         matrix4x4_t projection;
10776         decalsystem_t *decalsystem;
10777         qboolean dynamic;
10778         dp_model_t *model;
10779         const msurface_t *surface;
10780         const msurface_t *surfaces;
10781         const int *surfacelist;
10782         const texture_t *texture;
10783         int numtriangles;
10784         int numsurfacelist;
10785         int surfacelistindex;
10786         int surfaceindex;
10787         int triangleindex;
10788         float localorigin[3];
10789         float localnormal[3];
10790         float localmins[3];
10791         float localmaxs[3];
10792         float localsize;
10793         //float normal[3];
10794         float planes[6][4];
10795         float angles[3];
10796         bih_t *bih;
10797         int bih_triangles_count;
10798         int bih_triangles[256];
10799         int bih_surfaces[256];
10800
10801         decalsystem = &ent->decalsystem;
10802         model = ent->model;
10803         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10804         {
10805                 R_DecalSystem_Reset(&ent->decalsystem);
10806                 return;
10807         }
10808
10809         if (!model->brush.data_leafs && !cl_decals_models.integer)
10810         {
10811                 if (decalsystem->model)
10812                         R_DecalSystem_Reset(decalsystem);
10813                 return;
10814         }
10815
10816         if (decalsystem->model != model)
10817                 R_DecalSystem_Reset(decalsystem);
10818         decalsystem->model = model;
10819
10820         RSurf_ActiveModelEntity(ent, true, false, false);
10821
10822         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10823         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10824         VectorNormalize(localnormal);
10825         localsize = worldsize*rsurface.inversematrixscale;
10826         localmins[0] = localorigin[0] - localsize;
10827         localmins[1] = localorigin[1] - localsize;
10828         localmins[2] = localorigin[2] - localsize;
10829         localmaxs[0] = localorigin[0] + localsize;
10830         localmaxs[1] = localorigin[1] + localsize;
10831         localmaxs[2] = localorigin[2] + localsize;
10832
10833         //VectorCopy(localnormal, planes[4]);
10834         //VectorVectors(planes[4], planes[2], planes[0]);
10835         AnglesFromVectors(angles, localnormal, NULL, false);
10836         AngleVectors(angles, planes[0], planes[2], planes[4]);
10837         VectorNegate(planes[0], planes[1]);
10838         VectorNegate(planes[2], planes[3]);
10839         VectorNegate(planes[4], planes[5]);
10840         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10841         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10842         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10843         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10844         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10845         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10846
10847 #if 1
10848 // works
10849 {
10850         matrix4x4_t forwardprojection;
10851         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10852         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10853 }
10854 #else
10855 // broken
10856 {
10857         float projectionvector[4][3];
10858         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10859         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10860         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10861         projectionvector[0][0] = planes[0][0] * ilocalsize;
10862         projectionvector[0][1] = planes[1][0] * ilocalsize;
10863         projectionvector[0][2] = planes[2][0] * ilocalsize;
10864         projectionvector[1][0] = planes[0][1] * ilocalsize;
10865         projectionvector[1][1] = planes[1][1] * ilocalsize;
10866         projectionvector[1][2] = planes[2][1] * ilocalsize;
10867         projectionvector[2][0] = planes[0][2] * ilocalsize;
10868         projectionvector[2][1] = planes[1][2] * ilocalsize;
10869         projectionvector[2][2] = planes[2][2] * ilocalsize;
10870         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10871         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10872         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10873         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10874 }
10875 #endif
10876
10877         dynamic = model->surfmesh.isanimated;
10878         numsurfacelist = model->nummodelsurfaces;
10879         surfacelist = model->sortedmodelsurfaces;
10880         surfaces = model->data_surfaces;
10881
10882         bih = NULL;
10883         bih_triangles_count = -1;
10884         if(!dynamic)
10885         {
10886                 if(model->render_bih.numleafs)
10887                         bih = &model->render_bih;
10888                 else if(model->collision_bih.numleafs)
10889                         bih = &model->collision_bih;
10890         }
10891         if(bih)
10892                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10893         if(bih_triangles_count == 0)
10894                 return;
10895         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10896                 return;
10897         if(bih_triangles_count > 0)
10898         {
10899                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10900                 {
10901                         surfaceindex = bih_surfaces[triangleindex];
10902                         surface = surfaces + surfaceindex;
10903                         texture = surface->texture;
10904                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10905                                 continue;
10906                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10907                                 continue;
10908                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10909                 }
10910         }
10911         else
10912         {
10913                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10914                 {
10915                         surfaceindex = surfacelist[surfacelistindex];
10916                         surface = surfaces + surfaceindex;
10917                         // check cull box first because it rejects more than any other check
10918                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10919                                 continue;
10920                         // skip transparent surfaces
10921                         texture = surface->texture;
10922                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10923                                 continue;
10924                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10925                                 continue;
10926                         numtriangles = surface->num_triangles;
10927                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10928                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10929                 }
10930         }
10931 }
10932
10933 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10934 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)
10935 {
10936         int renderentityindex;
10937         float worldmins[3];
10938         float worldmaxs[3];
10939         entity_render_t *ent;
10940
10941         if (!cl_decals_newsystem.integer)
10942                 return;
10943
10944         worldmins[0] = worldorigin[0] - worldsize;
10945         worldmins[1] = worldorigin[1] - worldsize;
10946         worldmins[2] = worldorigin[2] - worldsize;
10947         worldmaxs[0] = worldorigin[0] + worldsize;
10948         worldmaxs[1] = worldorigin[1] + worldsize;
10949         worldmaxs[2] = worldorigin[2] + worldsize;
10950
10951         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10952
10953         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10954         {
10955                 ent = r_refdef.scene.entities[renderentityindex];
10956                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10957                         continue;
10958
10959                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10960         }
10961 }
10962
10963 typedef struct r_decalsystem_splatqueue_s
10964 {
10965         vec3_t worldorigin;
10966         vec3_t worldnormal;
10967         float color[4];
10968         float tcrange[4];
10969         float worldsize;
10970         int decalsequence;
10971 }
10972 r_decalsystem_splatqueue_t;
10973
10974 int r_decalsystem_numqueued = 0;
10975 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10976
10977 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)
10978 {
10979         r_decalsystem_splatqueue_t *queue;
10980
10981         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10982                 return;
10983
10984         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10985         VectorCopy(worldorigin, queue->worldorigin);
10986         VectorCopy(worldnormal, queue->worldnormal);
10987         Vector4Set(queue->color, r, g, b, a);
10988         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10989         queue->worldsize = worldsize;
10990         queue->decalsequence = cl.decalsequence++;
10991 }
10992
10993 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10994 {
10995         int i;
10996         r_decalsystem_splatqueue_t *queue;
10997
10998         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10999                 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);
11000         r_decalsystem_numqueued = 0;
11001 }
11002
11003 extern cvar_t cl_decals_max;
11004 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11005 {
11006         int i;
11007         decalsystem_t *decalsystem = &ent->decalsystem;
11008         int numdecals;
11009         int killsequence;
11010         tridecal_t *decal;
11011         float frametime;
11012         float lifetime;
11013
11014         if (!decalsystem->numdecals)
11015                 return;
11016
11017         if (r_showsurfaces.integer)
11018                 return;
11019
11020         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11021         {
11022                 R_DecalSystem_Reset(decalsystem);
11023                 return;
11024         }
11025
11026         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11027         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11028
11029         if (decalsystem->lastupdatetime)
11030                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11031         else
11032                 frametime = 0;
11033         decalsystem->lastupdatetime = r_refdef.scene.time;
11034         decal = decalsystem->decals;
11035         numdecals = decalsystem->numdecals;
11036
11037         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11038         {
11039                 if (decal->color4f[0][3])
11040                 {
11041                         decal->lived += frametime;
11042                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11043                         {
11044                                 memset(decal, 0, sizeof(*decal));
11045                                 if (decalsystem->freedecal > i)
11046                                         decalsystem->freedecal = i;
11047                         }
11048                 }
11049         }
11050         decal = decalsystem->decals;
11051         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11052                 numdecals--;
11053
11054         // collapse the array by shuffling the tail decals into the gaps
11055         for (;;)
11056         {
11057                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11058                         decalsystem->freedecal++;
11059                 if (decalsystem->freedecal == numdecals)
11060                         break;
11061                 decal[decalsystem->freedecal] = decal[--numdecals];
11062         }
11063
11064         decalsystem->numdecals = numdecals;
11065
11066         if (numdecals <= 0)
11067         {
11068                 // if there are no decals left, reset decalsystem
11069                 R_DecalSystem_Reset(decalsystem);
11070         }
11071 }
11072
11073 extern skinframe_t *decalskinframe;
11074 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11075 {
11076         int i;
11077         decalsystem_t *decalsystem = &ent->decalsystem;
11078         int numdecals;
11079         tridecal_t *decal;
11080         float faderate;
11081         float alpha;
11082         float *v3f;
11083         float *c4f;
11084         float *t2f;
11085         const int *e;
11086         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11087         int numtris = 0;
11088
11089         numdecals = decalsystem->numdecals;
11090         if (!numdecals)
11091                 return;
11092
11093         if (r_showsurfaces.integer)
11094                 return;
11095
11096         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11097         {
11098                 R_DecalSystem_Reset(decalsystem);
11099                 return;
11100         }
11101
11102         // if the model is static it doesn't matter what value we give for
11103         // wantnormals and wanttangents, so this logic uses only rules applicable
11104         // to a model, knowing that they are meaningless otherwise
11105         if (ent == r_refdef.scene.worldentity)
11106                 RSurf_ActiveWorldEntity();
11107         else
11108                 RSurf_ActiveModelEntity(ent, false, false, false);
11109
11110         decalsystem->lastupdatetime = r_refdef.scene.time;
11111         decal = decalsystem->decals;
11112
11113         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11114
11115         // update vertex positions for animated models
11116         v3f = decalsystem->vertex3f;
11117         c4f = decalsystem->color4f;
11118         t2f = decalsystem->texcoord2f;
11119         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11120         {
11121                 if (!decal->color4f[0][3])
11122                         continue;
11123
11124                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11125                         continue;
11126
11127                 // skip backfaces
11128                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11129                         continue;
11130
11131                 // update color values for fading decals
11132                 if (decal->lived >= cl_decals_time.value)
11133                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11134                 else
11135                         alpha = 1.0f;
11136
11137                 c4f[ 0] = decal->color4f[0][0] * alpha;
11138                 c4f[ 1] = decal->color4f[0][1] * alpha;
11139                 c4f[ 2] = decal->color4f[0][2] * alpha;
11140                 c4f[ 3] = 1;
11141                 c4f[ 4] = decal->color4f[1][0] * alpha;
11142                 c4f[ 5] = decal->color4f[1][1] * alpha;
11143                 c4f[ 6] = decal->color4f[1][2] * alpha;
11144                 c4f[ 7] = 1;
11145                 c4f[ 8] = decal->color4f[2][0] * alpha;
11146                 c4f[ 9] = decal->color4f[2][1] * alpha;
11147                 c4f[10] = decal->color4f[2][2] * alpha;
11148                 c4f[11] = 1;
11149
11150                 t2f[0] = decal->texcoord2f[0][0];
11151                 t2f[1] = decal->texcoord2f[0][1];
11152                 t2f[2] = decal->texcoord2f[1][0];
11153                 t2f[3] = decal->texcoord2f[1][1];
11154                 t2f[4] = decal->texcoord2f[2][0];
11155                 t2f[5] = decal->texcoord2f[2][1];
11156
11157                 // update vertex positions for animated models
11158                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11159                 {
11160                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11161                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11162                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11163                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11164                 }
11165                 else
11166                 {
11167                         VectorCopy(decal->vertex3f[0], v3f);
11168                         VectorCopy(decal->vertex3f[1], v3f + 3);
11169                         VectorCopy(decal->vertex3f[2], v3f + 6);
11170                 }
11171
11172                 if (r_refdef.fogenabled)
11173                 {
11174                         alpha = RSurf_FogVertex(v3f);
11175                         VectorScale(c4f, alpha, c4f);
11176                         alpha = RSurf_FogVertex(v3f + 3);
11177                         VectorScale(c4f + 4, alpha, c4f + 4);
11178                         alpha = RSurf_FogVertex(v3f + 6);
11179                         VectorScale(c4f + 8, alpha, c4f + 8);
11180                 }
11181
11182                 v3f += 9;
11183                 c4f += 12;
11184                 t2f += 6;
11185                 numtris++;
11186         }
11187
11188         if (numtris > 0)
11189         {
11190                 r_refdef.stats.drawndecals += numtris;
11191
11192                 // now render the decals all at once
11193                 // (this assumes they all use one particle font texture!)
11194                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11195 //              R_Mesh_ResetTextureState();
11196                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11197                 GL_DepthMask(false);
11198                 GL_DepthRange(0, 1);
11199                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11200                 GL_DepthTest(true);
11201                 GL_CullFace(GL_NONE);
11202                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11203                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11204                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11205         }
11206 }
11207
11208 static void R_DrawModelDecals(void)
11209 {
11210         int i, numdecals;
11211
11212         // fade faster when there are too many decals
11213         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11214         for (i = 0;i < r_refdef.scene.numentities;i++)
11215                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11216
11217         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11218         for (i = 0;i < r_refdef.scene.numentities;i++)
11219                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11220                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11221
11222         R_DecalSystem_ApplySplatEntitiesQueue();
11223
11224         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11225         for (i = 0;i < r_refdef.scene.numentities;i++)
11226                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11227
11228         r_refdef.stats.totaldecals += numdecals;
11229
11230         if (r_showsurfaces.integer)
11231                 return;
11232
11233         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11234
11235         for (i = 0;i < r_refdef.scene.numentities;i++)
11236         {
11237                 if (!r_refdef.viewcache.entityvisible[i])
11238                         continue;
11239                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11240                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11241         }
11242 }
11243
11244 extern cvar_t mod_collision_bih;
11245 void R_DrawDebugModel(void)
11246 {
11247         entity_render_t *ent = rsurface.entity;
11248         int i, j, k, l, flagsmask;
11249         const msurface_t *surface;
11250         dp_model_t *model = ent->model;
11251         vec3_t v;
11252
11253         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11254                 return;
11255
11256         if (r_showoverdraw.value > 0)
11257         {
11258                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11259                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11260                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11261                 GL_DepthTest(false);
11262                 GL_DepthMask(false);
11263                 GL_DepthRange(0, 1);
11264                 GL_BlendFunc(GL_ONE, GL_ONE);
11265                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11266                 {
11267                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11268                                 continue;
11269                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11270                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11271                         {
11272                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11273                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11274                                 if (!rsurface.texture->currentlayers->depthmask)
11275                                         GL_Color(c, 0, 0, 1.0f);
11276                                 else if (ent == r_refdef.scene.worldentity)
11277                                         GL_Color(c, c, c, 1.0f);
11278                                 else
11279                                         GL_Color(0, c, 0, 1.0f);
11280                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11281                                 RSurf_DrawBatch();
11282                         }
11283                 }
11284                 rsurface.texture = NULL;
11285         }
11286
11287         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11288
11289 //      R_Mesh_ResetTextureState();
11290         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11291         GL_DepthRange(0, 1);
11292         GL_DepthTest(!r_showdisabledepthtest.integer);
11293         GL_DepthMask(false);
11294         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11295
11296         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11297         {
11298                 int triangleindex;
11299                 int bihleafindex;
11300                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11301                 const q3mbrush_t *brush;
11302                 const bih_t *bih = &model->collision_bih;
11303                 const bih_leaf_t *bihleaf;
11304                 float vertex3f[3][3];
11305                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11306                 cullbox = false;
11307                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11308                 {
11309                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11310                                 continue;
11311                         switch (bihleaf->type)
11312                         {
11313                         case BIH_BRUSH:
11314                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11315                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11316                                 {
11317                                         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);
11318                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11319                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11320                                 }
11321                                 break;
11322                         case BIH_COLLISIONTRIANGLE:
11323                                 triangleindex = bihleaf->itemindex;
11324                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11325                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11326                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11327                                 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);
11328                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11329                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11330                                 break;
11331                         case BIH_RENDERTRIANGLE:
11332                                 triangleindex = bihleaf->itemindex;
11333                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11334                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11335                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11336                                 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);
11337                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11338                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11339                                 break;
11340                         }
11341                 }
11342         }
11343
11344         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11345
11346         if (r_showtris.integer && qglPolygonMode)
11347         {
11348                 if (r_showdisabledepthtest.integer)
11349                 {
11350                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11351                         GL_DepthMask(false);
11352                 }
11353                 else
11354                 {
11355                         GL_BlendFunc(GL_ONE, GL_ZERO);
11356                         GL_DepthMask(true);
11357                 }
11358                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11359                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11360                 {
11361                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11362                                 continue;
11363                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11364                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11365                         {
11366                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11367                                 if (!rsurface.texture->currentlayers->depthmask)
11368                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11369                                 else if (ent == r_refdef.scene.worldentity)
11370                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11371                                 else
11372                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11373                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11374                                 RSurf_DrawBatch();
11375                         }
11376                 }
11377                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11378                 rsurface.texture = NULL;
11379         }
11380
11381         if (r_shownormals.value != 0 && qglBegin)
11382         {
11383                 if (r_showdisabledepthtest.integer)
11384                 {
11385                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11386                         GL_DepthMask(false);
11387                 }
11388                 else
11389                 {
11390                         GL_BlendFunc(GL_ONE, GL_ZERO);
11391                         GL_DepthMask(true);
11392                 }
11393                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11394                 {
11395                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11396                                 continue;
11397                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11398                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11399                         {
11400                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11401                                 qglBegin(GL_LINES);
11402                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11403                                 {
11404                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11405                                         {
11406                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11407                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11408                                                 qglVertex3f(v[0], v[1], v[2]);
11409                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11410                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11411                                                 qglVertex3f(v[0], v[1], v[2]);
11412                                         }
11413                                 }
11414                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11415                                 {
11416                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11417                                         {
11418                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11419                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11420                                                 qglVertex3f(v[0], v[1], v[2]);
11421                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11422                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11423                                                 qglVertex3f(v[0], v[1], v[2]);
11424                                         }
11425                                 }
11426                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11427                                 {
11428                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11429                                         {
11430                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11431                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11432                                                 qglVertex3f(v[0], v[1], v[2]);
11433                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11434                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11435                                                 qglVertex3f(v[0], v[1], v[2]);
11436                                         }
11437                                 }
11438                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11439                                 {
11440                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11441                                         {
11442                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11443                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11444                                                 qglVertex3f(v[0], v[1], v[2]);
11445                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11446                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11447                                                 qglVertex3f(v[0], v[1], v[2]);
11448                                         }
11449                                 }
11450                                 qglEnd();
11451                                 CHECKGLERROR
11452                         }
11453                 }
11454                 rsurface.texture = NULL;
11455         }
11456 }
11457
11458 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11459 int r_maxsurfacelist = 0;
11460 const msurface_t **r_surfacelist = NULL;
11461 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11462 {
11463         int i, j, endj, flagsmask;
11464         dp_model_t *model = r_refdef.scene.worldmodel;
11465         msurface_t *surfaces;
11466         unsigned char *update;
11467         int numsurfacelist = 0;
11468         if (model == NULL)
11469                 return;
11470
11471         if (r_maxsurfacelist < model->num_surfaces)
11472         {
11473                 r_maxsurfacelist = model->num_surfaces;
11474                 if (r_surfacelist)
11475                         Mem_Free((msurface_t**)r_surfacelist);
11476                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11477         }
11478
11479         RSurf_ActiveWorldEntity();
11480
11481         surfaces = model->data_surfaces;
11482         update = model->brushq1.lightmapupdateflags;
11483
11484         // update light styles on this submodel
11485         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11486         {
11487                 model_brush_lightstyleinfo_t *style;
11488                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11489                 {
11490                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11491                         {
11492                                 int *list = style->surfacelist;
11493                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11494                                 for (j = 0;j < style->numsurfaces;j++)
11495                                         update[list[j]] = true;
11496                         }
11497                 }
11498         }
11499
11500         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11501
11502         if (debug)
11503         {
11504                 R_DrawDebugModel();
11505                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11506                 return;
11507         }
11508
11509         rsurface.lightmaptexture = NULL;
11510         rsurface.deluxemaptexture = NULL;
11511         rsurface.uselightmaptexture = false;
11512         rsurface.texture = NULL;
11513         rsurface.rtlight = NULL;
11514         numsurfacelist = 0;
11515         // add visible surfaces to draw list
11516         for (i = 0;i < model->nummodelsurfaces;i++)
11517         {
11518                 j = model->sortedmodelsurfaces[i];
11519                 if (r_refdef.viewcache.world_surfacevisible[j])
11520                         r_surfacelist[numsurfacelist++] = surfaces + j;
11521         }
11522         // update lightmaps if needed
11523         if (model->brushq1.firstrender)
11524         {
11525                 model->brushq1.firstrender = false;
11526                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11527                         if (update[j])
11528                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11529         }
11530         else if (update)
11531         {
11532                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11533                         if (r_refdef.viewcache.world_surfacevisible[j])
11534                                 if (update[j])
11535                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11536         }
11537         // don't do anything if there were no surfaces
11538         if (!numsurfacelist)
11539         {
11540                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11541                 return;
11542         }
11543         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11544
11545         // add to stats if desired
11546         if (r_speeds.integer && !skysurfaces && !depthonly)
11547         {
11548                 r_refdef.stats.world_surfaces += numsurfacelist;
11549                 for (j = 0;j < numsurfacelist;j++)
11550                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11551         }
11552
11553         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11554 }
11555
11556 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11557 {
11558         int i, j, endj, flagsmask;
11559         dp_model_t *model = ent->model;
11560         msurface_t *surfaces;
11561         unsigned char *update;
11562         int numsurfacelist = 0;
11563         if (model == NULL)
11564                 return;
11565
11566         if (r_maxsurfacelist < model->num_surfaces)
11567         {
11568                 r_maxsurfacelist = model->num_surfaces;
11569                 if (r_surfacelist)
11570                         Mem_Free((msurface_t **)r_surfacelist);
11571                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11572         }
11573
11574         // if the model is static it doesn't matter what value we give for
11575         // wantnormals and wanttangents, so this logic uses only rules applicable
11576         // to a model, knowing that they are meaningless otherwise
11577         if (ent == r_refdef.scene.worldentity)
11578                 RSurf_ActiveWorldEntity();
11579         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11580                 RSurf_ActiveModelEntity(ent, false, false, false);
11581         else if (prepass)
11582                 RSurf_ActiveModelEntity(ent, true, true, true);
11583         else if (depthonly)
11584         {
11585                 switch (vid.renderpath)
11586                 {
11587                 case RENDERPATH_GL20:
11588                 case RENDERPATH_D3D9:
11589                 case RENDERPATH_D3D10:
11590                 case RENDERPATH_D3D11:
11591                 case RENDERPATH_SOFT:
11592                 case RENDERPATH_GLES2:
11593                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11594                         break;
11595                 case RENDERPATH_GL11:
11596                 case RENDERPATH_GL13:
11597                 case RENDERPATH_GLES1:
11598                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11599                         break;
11600                 }
11601         }
11602         else
11603         {
11604                 switch (vid.renderpath)
11605                 {
11606                 case RENDERPATH_GL20:
11607                 case RENDERPATH_D3D9:
11608                 case RENDERPATH_D3D10:
11609                 case RENDERPATH_D3D11:
11610                 case RENDERPATH_SOFT:
11611                 case RENDERPATH_GLES2:
11612                         RSurf_ActiveModelEntity(ent, true, true, false);
11613                         break;
11614                 case RENDERPATH_GL11:
11615                 case RENDERPATH_GL13:
11616                 case RENDERPATH_GLES1:
11617                         RSurf_ActiveModelEntity(ent, true, false, false);
11618                         break;
11619                 }
11620         }
11621
11622         surfaces = model->data_surfaces;
11623         update = model->brushq1.lightmapupdateflags;
11624
11625         // update light styles
11626         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11627         {
11628                 model_brush_lightstyleinfo_t *style;
11629                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11630                 {
11631                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11632                         {
11633                                 int *list = style->surfacelist;
11634                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11635                                 for (j = 0;j < style->numsurfaces;j++)
11636                                         update[list[j]] = true;
11637                         }
11638                 }
11639         }
11640
11641         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11642
11643         if (debug)
11644         {
11645                 R_DrawDebugModel();
11646                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11647                 return;
11648         }
11649
11650         rsurface.lightmaptexture = NULL;
11651         rsurface.deluxemaptexture = NULL;
11652         rsurface.uselightmaptexture = false;
11653         rsurface.texture = NULL;
11654         rsurface.rtlight = NULL;
11655         numsurfacelist = 0;
11656         // add visible surfaces to draw list
11657         for (i = 0;i < model->nummodelsurfaces;i++)
11658                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11659         // don't do anything if there were no surfaces
11660         if (!numsurfacelist)
11661         {
11662                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11663                 return;
11664         }
11665         // update lightmaps if needed
11666         if (update)
11667         {
11668                 int updated = 0;
11669                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11670                 {
11671                         if (update[j])
11672                         {
11673                                 updated++;
11674                                 R_BuildLightMap(ent, surfaces + j);
11675                         }
11676                 }
11677         }
11678         if (update)
11679                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11680                         if (update[j])
11681                                 R_BuildLightMap(ent, surfaces + j);
11682         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11683
11684         // add to stats if desired
11685         if (r_speeds.integer && !skysurfaces && !depthonly)
11686         {
11687                 r_refdef.stats.entities_surfaces += numsurfacelist;
11688                 for (j = 0;j < numsurfacelist;j++)
11689                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11690         }
11691
11692         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11693 }
11694
11695 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11696 {
11697         static texture_t texture;
11698         static msurface_t surface;
11699         const msurface_t *surfacelist = &surface;
11700
11701         // fake enough texture and surface state to render this geometry
11702
11703         texture.update_lastrenderframe = -1; // regenerate this texture
11704         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11705         texture.currentskinframe = skinframe;
11706         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11707         texture.offsetmapping = OFFSETMAPPING_OFF;
11708         texture.offsetscale = 1;
11709         texture.specularscalemod = 1;
11710         texture.specularpowermod = 1;
11711
11712         surface.texture = &texture;
11713         surface.num_triangles = numtriangles;
11714         surface.num_firsttriangle = firsttriangle;
11715         surface.num_vertices = numvertices;
11716         surface.num_firstvertex = firstvertex;
11717
11718         // now render it
11719         rsurface.texture = R_GetCurrentTexture(surface.texture);
11720         rsurface.lightmaptexture = NULL;
11721         rsurface.deluxemaptexture = NULL;
11722         rsurface.uselightmaptexture = false;
11723         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11724 }
11725
11726 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)
11727 {
11728         static msurface_t surface;
11729         const msurface_t *surfacelist = &surface;
11730
11731         // fake enough texture and surface state to render this geometry
11732         surface.texture = texture;
11733         surface.num_triangles = numtriangles;
11734         surface.num_firsttriangle = firsttriangle;
11735         surface.num_vertices = numvertices;
11736         surface.num_firstvertex = firstvertex;
11737
11738         // now render it
11739         rsurface.texture = R_GetCurrentTexture(surface.texture);
11740         rsurface.lightmaptexture = NULL;
11741         rsurface.deluxemaptexture = NULL;
11742         rsurface.uselightmaptexture = false;
11743         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11744 }