]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Offsetmapping: new "Bias" parameter that sets a custom "null point" instead of always...
[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_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 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."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 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."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 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"};
123 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"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 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"};
130 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
131 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
132
133 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
134 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
135 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
136 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
137 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
138 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
139 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
140 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
141
142 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)"};
143 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"};
144
145 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
146 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
147 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
148
149 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"};
150 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"};
151 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
152 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
153 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"};
154 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)"};
155 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)"};
156 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
157
158 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)"};
159 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
160 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)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
162 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)"};
163 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)"};
164 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
165 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
166 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
167 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176
177 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)"};
178 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
179 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"};
180 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
181 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
182 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
183 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"};
184
185 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
186 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
187 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
188 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
189
190 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
191 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
192 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
193 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
194 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
195 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
196 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
197
198 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
199 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
200 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
201 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)"};
202 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
203 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
204 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
207 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
208 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
209
210 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"};
211
212 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"};
213
214 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
215
216 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
217
218 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
219 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"};
220
221 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."};
222
223 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)"};
224
225 extern cvar_t v_glslgamma;
226 extern cvar_t v_glslgamma_2d;
227
228 extern qboolean v_flipped_state;
229
230 static struct r_bloomstate_s
231 {
232         qboolean enabled;
233         qboolean hdr;
234
235         int bloomwidth, bloomheight;
236
237         textype_t texturetype;
238         int viewfbo; // used to check if r_viewfbo cvar has changed
239
240         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
241         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
242         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
243
244         int screentexturewidth, screentextureheight;
245         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
246
247         int bloomtexturewidth, bloomtextureheight;
248         rtexture_t *texture_bloom;
249
250         // arrays for rendering the screen passes
251         float screentexcoord2f[8];
252         float bloomtexcoord2f[8];
253         float offsettexcoord2f[8];
254
255         r_viewport_t viewport;
256 }
257 r_bloomstate;
258
259 r_waterstate_t r_waterstate;
260
261 /// shadow volume bsp struct with automatically growing nodes buffer
262 svbsp_t r_svbsp;
263
264 rtexture_t *r_texture_blanknormalmap;
265 rtexture_t *r_texture_white;
266 rtexture_t *r_texture_grey128;
267 rtexture_t *r_texture_black;
268 rtexture_t *r_texture_notexture;
269 rtexture_t *r_texture_whitecube;
270 rtexture_t *r_texture_normalizationcube;
271 rtexture_t *r_texture_fogattenuation;
272 rtexture_t *r_texture_fogheighttexture;
273 rtexture_t *r_texture_gammaramps;
274 unsigned int r_texture_gammaramps_serial;
275 //rtexture_t *r_texture_fogintensity;
276 rtexture_t *r_texture_reflectcube;
277
278 // TODO: hash lookups?
279 typedef struct cubemapinfo_s
280 {
281         char basename[64];
282         rtexture_t *texture;
283 }
284 cubemapinfo_t;
285
286 int r_texture_numcubemaps;
287 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
288
289 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
290 unsigned int r_numqueries;
291 unsigned int r_maxqueries;
292
293 typedef struct r_qwskincache_s
294 {
295         char name[MAX_QPATH];
296         skinframe_t *skinframe;
297 }
298 r_qwskincache_t;
299
300 static r_qwskincache_t *r_qwskincache;
301 static int r_qwskincache_size;
302
303 /// vertex coordinates for a quad that covers the screen exactly
304 extern const float r_screenvertex3f[12];
305 extern const float r_d3dscreenvertex3f[12];
306 const float r_screenvertex3f[12] =
307 {
308         0, 0, 0,
309         1, 0, 0,
310         1, 1, 0,
311         0, 1, 0
312 };
313 const float r_d3dscreenvertex3f[12] =
314 {
315         0, 1, 0,
316         1, 1, 0,
317         1, 0, 0,
318         0, 0, 0
319 };
320
321 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
322 {
323         int i;
324         for (i = 0;i < verts;i++)
325         {
326                 out[0] = in[0] * r;
327                 out[1] = in[1] * g;
328                 out[2] = in[2] * b;
329                 out[3] = in[3];
330                 in += 4;
331                 out += 4;
332         }
333 }
334
335 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
336 {
337         int i;
338         for (i = 0;i < verts;i++)
339         {
340                 out[0] = r;
341                 out[1] = g;
342                 out[2] = b;
343                 out[3] = a;
344                 out += 4;
345         }
346 }
347
348 // FIXME: move this to client?
349 void FOG_clear(void)
350 {
351         if (gamemode == GAME_NEHAHRA)
352         {
353                 Cvar_Set("gl_fogenable", "0");
354                 Cvar_Set("gl_fogdensity", "0.2");
355                 Cvar_Set("gl_fogred", "0.3");
356                 Cvar_Set("gl_foggreen", "0.3");
357                 Cvar_Set("gl_fogblue", "0.3");
358         }
359         r_refdef.fog_density = 0;
360         r_refdef.fog_red = 0;
361         r_refdef.fog_green = 0;
362         r_refdef.fog_blue = 0;
363         r_refdef.fog_alpha = 1;
364         r_refdef.fog_start = 0;
365         r_refdef.fog_end = 16384;
366         r_refdef.fog_height = 1<<30;
367         r_refdef.fog_fadedepth = 128;
368         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
369 }
370
371 static void R_BuildBlankTextures(void)
372 {
373         unsigned char data[4];
374         data[2] = 128; // normal X
375         data[1] = 128; // normal Y
376         data[0] = 255; // normal Z
377         data[3] = 128; // height
378         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379         data[0] = 255;
380         data[1] = 255;
381         data[2] = 255;
382         data[3] = 255;
383         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384         data[0] = 128;
385         data[1] = 128;
386         data[2] = 128;
387         data[3] = 255;
388         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389         data[0] = 0;
390         data[1] = 0;
391         data[2] = 0;
392         data[3] = 255;
393         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 }
395
396 static void R_BuildNoTexture(void)
397 {
398         int x, y;
399         unsigned char pix[16][16][4];
400         // this makes a light grey/dark grey checkerboard texture
401         for (y = 0;y < 16;y++)
402         {
403                 for (x = 0;x < 16;x++)
404                 {
405                         if ((y < 8) ^ (x < 8))
406                         {
407                                 pix[y][x][0] = 128;
408                                 pix[y][x][1] = 128;
409                                 pix[y][x][2] = 128;
410                                 pix[y][x][3] = 255;
411                         }
412                         else
413                         {
414                                 pix[y][x][0] = 64;
415                                 pix[y][x][1] = 64;
416                                 pix[y][x][2] = 64;
417                                 pix[y][x][3] = 255;
418                         }
419                 }
420         }
421         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
422 }
423
424 static void R_BuildWhiteCube(void)
425 {
426         unsigned char data[6*1*1*4];
427         memset(data, 255, sizeof(data));
428         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
429 }
430
431 static void R_BuildNormalizationCube(void)
432 {
433         int x, y, side;
434         vec3_t v;
435         vec_t s, t, intensity;
436 #define NORMSIZE 64
437         unsigned char *data;
438         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
439         for (side = 0;side < 6;side++)
440         {
441                 for (y = 0;y < NORMSIZE;y++)
442                 {
443                         for (x = 0;x < NORMSIZE;x++)
444                         {
445                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
446                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447                                 switch(side)
448                                 {
449                                 default:
450                                 case 0:
451                                         v[0] = 1;
452                                         v[1] = -t;
453                                         v[2] = -s;
454                                         break;
455                                 case 1:
456                                         v[0] = -1;
457                                         v[1] = -t;
458                                         v[2] = s;
459                                         break;
460                                 case 2:
461                                         v[0] = s;
462                                         v[1] = 1;
463                                         v[2] = t;
464                                         break;
465                                 case 3:
466                                         v[0] = s;
467                                         v[1] = -1;
468                                         v[2] = -t;
469                                         break;
470                                 case 4:
471                                         v[0] = s;
472                                         v[1] = -t;
473                                         v[2] = 1;
474                                         break;
475                                 case 5:
476                                         v[0] = -s;
477                                         v[1] = -t;
478                                         v[2] = -1;
479                                         break;
480                                 }
481                                 intensity = 127.0f / sqrt(DotProduct(v, v));
482                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
483                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
484                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
485                                 data[((side*64+y)*64+x)*4+3] = 255;
486                         }
487                 }
488         }
489         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490         Mem_Free(data);
491 }
492
493 static void R_BuildFogTexture(void)
494 {
495         int x, b;
496 #define FOGWIDTH 256
497         unsigned char data1[FOGWIDTH][4];
498         //unsigned char data2[FOGWIDTH][4];
499         double d, r, alpha;
500
501         r_refdef.fogmasktable_start = r_refdef.fog_start;
502         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
503         r_refdef.fogmasktable_range = r_refdef.fogrange;
504         r_refdef.fogmasktable_density = r_refdef.fog_density;
505
506         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
507         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
508         {
509                 d = (x * r - r_refdef.fogmasktable_start);
510                 if(developer_extra.integer)
511                         Con_DPrintf("%f ", d);
512                 d = max(0, d);
513                 if (r_fog_exp2.integer)
514                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
515                 else
516                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
517                 if(developer_extra.integer)
518                         Con_DPrintf(" : %f ", alpha);
519                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
520                 if(developer_extra.integer)
521                         Con_DPrintf(" = %f\n", alpha);
522                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
523         }
524
525         for (x = 0;x < FOGWIDTH;x++)
526         {
527                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
528                 data1[x][0] = b;
529                 data1[x][1] = b;
530                 data1[x][2] = b;
531                 data1[x][3] = 255;
532                 //data2[x][0] = 255 - b;
533                 //data2[x][1] = 255 - b;
534                 //data2[x][2] = 255 - b;
535                 //data2[x][3] = 255;
536         }
537         if (r_texture_fogattenuation)
538         {
539                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541         }
542         else
543         {
544                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
545                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546         }
547 }
548
549 static void R_BuildFogHeightTexture(void)
550 {
551         unsigned char *inpixels;
552         int size;
553         int x;
554         int y;
555         int j;
556         float c[4];
557         float f;
558         inpixels = NULL;
559         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
560         if (r_refdef.fogheighttexturename[0])
561                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
562         if (!inpixels)
563         {
564                 r_refdef.fog_height_tablesize = 0;
565                 if (r_texture_fogheighttexture)
566                         R_FreeTexture(r_texture_fogheighttexture);
567                 r_texture_fogheighttexture = NULL;
568                 if (r_refdef.fog_height_table2d)
569                         Mem_Free(r_refdef.fog_height_table2d);
570                 r_refdef.fog_height_table2d = NULL;
571                 if (r_refdef.fog_height_table1d)
572                         Mem_Free(r_refdef.fog_height_table1d);
573                 r_refdef.fog_height_table1d = NULL;
574                 return;
575         }
576         size = image_width;
577         r_refdef.fog_height_tablesize = size;
578         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
579         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
580         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
581         Mem_Free(inpixels);
582         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
583         // average fog color table accounting for every fog layer between a point
584         // and the camera.  (Note: attenuation is handled separately!)
585         for (y = 0;y < size;y++)
586         {
587                 for (x = 0;x < size;x++)
588                 {
589                         Vector4Clear(c);
590                         f = 0;
591                         if (x < y)
592                         {
593                                 for (j = x;j <= y;j++)
594                                 {
595                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
596                                         f++;
597                                 }
598                         }
599                         else
600                         {
601                                 for (j = x;j >= y;j--)
602                                 {
603                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
604                                         f++;
605                                 }
606                         }
607                         f = 1.0f / f;
608                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
612                 }
613         }
614         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
615 }
616
617 //=======================================================================================================================================================
618
619 static const char *builtinshaderstring =
620 #include "shader_glsl.h"
621 ;
622
623 const char *builtinhlslshaderstring =
624 #include "shader_hlsl.h"
625 ;
626
627 char *glslshaderstring = NULL;
628 char *hlslshaderstring = NULL;
629
630 //=======================================================================================================================================================
631
632 typedef struct shaderpermutationinfo_s
633 {
634         const char *pretext;
635         const char *name;
636 }
637 shaderpermutationinfo_t;
638
639 typedef struct shadermodeinfo_s
640 {
641         const char *vertexfilename;
642         const char *geometryfilename;
643         const char *fragmentfilename;
644         const char *pretext;
645         const char *name;
646 }
647 shadermodeinfo_t;
648
649 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
650 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {
652         {"#define USEDIFFUSE\n", " diffuse"},
653         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
654         {"#define USEVIEWTINT\n", " viewtint"},
655         {"#define USECOLORMAPPING\n", " colormapping"},
656         {"#define USESATURATION\n", " saturation"},
657         {"#define USEFOGINSIDE\n", " foginside"},
658         {"#define USEFOGOUTSIDE\n", " fogoutside"},
659         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
660         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
661         {"#define USEGAMMARAMPS\n", " gammaramps"},
662         {"#define USECUBEFILTER\n", " cubefilter"},
663         {"#define USEGLOW\n", " glow"},
664         {"#define USEBLOOM\n", " bloom"},
665         {"#define USESPECULAR\n", " specular"},
666         {"#define USEPOSTPROCESSING\n", " postprocessing"},
667         {"#define USEREFLECTION\n", " reflection"},
668         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
669         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
671         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
672         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
673         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
674         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
675         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
676         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
677         {"#define USEALPHAKILL\n", " alphakill"},
678         {"#define USEREFLECTCUBE\n", " reflectcube"},
679         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
680         {"#define USEBOUNCEGRID\n", " bouncegrid"},
681         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
682         {"#define USETRIPPY\n", " trippy"},
683 };
684
685 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
686 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 };
707
708 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
709 {
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
728 };
729
730 struct r_glsl_permutation_s;
731 typedef struct r_glsl_permutation_s
732 {
733         /// hash lookup data
734         struct r_glsl_permutation_s *hashnext;
735         unsigned int mode;
736         unsigned int permutation;
737
738         /// indicates if we have tried compiling this permutation already
739         qboolean compiled;
740         /// 0 if compilation failed
741         int program;
742         // texture units assigned to each detected uniform
743         int tex_Texture_First;
744         int tex_Texture_Second;
745         int tex_Texture_GammaRamps;
746         int tex_Texture_Normal;
747         int tex_Texture_Color;
748         int tex_Texture_Gloss;
749         int tex_Texture_Glow;
750         int tex_Texture_SecondaryNormal;
751         int tex_Texture_SecondaryColor;
752         int tex_Texture_SecondaryGloss;
753         int tex_Texture_SecondaryGlow;
754         int tex_Texture_Pants;
755         int tex_Texture_Shirt;
756         int tex_Texture_FogHeightTexture;
757         int tex_Texture_FogMask;
758         int tex_Texture_Lightmap;
759         int tex_Texture_Deluxemap;
760         int tex_Texture_Attenuation;
761         int tex_Texture_Cube;
762         int tex_Texture_Refraction;
763         int tex_Texture_Reflection;
764         int tex_Texture_ShadowMap2D;
765         int tex_Texture_CubeProjection;
766         int tex_Texture_ScreenDepth;
767         int tex_Texture_ScreenNormalMap;
768         int tex_Texture_ScreenDiffuse;
769         int tex_Texture_ScreenSpecular;
770         int tex_Texture_ReflectMask;
771         int tex_Texture_ReflectCube;
772         int tex_Texture_BounceGrid;
773         /// locations of detected uniforms in program object, or -1 if not found
774         int loc_Texture_First;
775         int loc_Texture_Second;
776         int loc_Texture_GammaRamps;
777         int loc_Texture_Normal;
778         int loc_Texture_Color;
779         int loc_Texture_Gloss;
780         int loc_Texture_Glow;
781         int loc_Texture_SecondaryNormal;
782         int loc_Texture_SecondaryColor;
783         int loc_Texture_SecondaryGloss;
784         int loc_Texture_SecondaryGlow;
785         int loc_Texture_Pants;
786         int loc_Texture_Shirt;
787         int loc_Texture_FogHeightTexture;
788         int loc_Texture_FogMask;
789         int loc_Texture_Lightmap;
790         int loc_Texture_Deluxemap;
791         int loc_Texture_Attenuation;
792         int loc_Texture_Cube;
793         int loc_Texture_Refraction;
794         int loc_Texture_Reflection;
795         int loc_Texture_ShadowMap2D;
796         int loc_Texture_CubeProjection;
797         int loc_Texture_ScreenDepth;
798         int loc_Texture_ScreenNormalMap;
799         int loc_Texture_ScreenDiffuse;
800         int loc_Texture_ScreenSpecular;
801         int loc_Texture_ReflectMask;
802         int loc_Texture_ReflectCube;
803         int loc_Texture_BounceGrid;
804         int loc_Alpha;
805         int loc_BloomBlur_Parameters;
806         int loc_ClientTime;
807         int loc_Color_Ambient;
808         int loc_Color_Diffuse;
809         int loc_Color_Specular;
810         int loc_Color_Glow;
811         int loc_Color_Pants;
812         int loc_Color_Shirt;
813         int loc_DeferredColor_Ambient;
814         int loc_DeferredColor_Diffuse;
815         int loc_DeferredColor_Specular;
816         int loc_DeferredMod_Diffuse;
817         int loc_DeferredMod_Specular;
818         int loc_DistortScaleRefractReflect;
819         int loc_EyePosition;
820         int loc_FogColor;
821         int loc_FogHeightFade;
822         int loc_FogPlane;
823         int loc_FogPlaneViewDist;
824         int loc_FogRangeRecip;
825         int loc_LightColor;
826         int loc_LightDir;
827         int loc_LightPosition;
828         int loc_OffsetMapping_ScaleSteps;
829         int loc_OffsetMapping_LodDistance;
830         int loc_OffsetMapping_Bias;
831         int loc_PixelSize;
832         int loc_ReflectColor;
833         int loc_ReflectFactor;
834         int loc_ReflectOffset;
835         int loc_RefractColor;
836         int loc_Saturation;
837         int loc_ScreenCenterRefractReflect;
838         int loc_ScreenScaleRefractReflect;
839         int loc_ScreenToDepth;
840         int loc_ShadowMap_Parameters;
841         int loc_ShadowMap_TextureScale;
842         int loc_SpecularPower;
843         int loc_UserVec1;
844         int loc_UserVec2;
845         int loc_UserVec3;
846         int loc_UserVec4;
847         int loc_ViewTintColor;
848         int loc_ViewToLight;
849         int loc_ModelToLight;
850         int loc_TexMatrix;
851         int loc_BackgroundTexMatrix;
852         int loc_ModelViewProjectionMatrix;
853         int loc_ModelViewMatrix;
854         int loc_PixelToScreenTexCoord;
855         int loc_ModelToReflectCube;
856         int loc_ShadowMapMatrix;
857         int loc_BloomColorSubtract;
858         int loc_NormalmapScrollBlend;
859         int loc_BounceGridMatrix;
860         int loc_BounceGridIntensity;
861 }
862 r_glsl_permutation_t;
863
864 #define SHADERPERMUTATION_HASHSIZE 256
865
866
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
869 enum
870 {
871         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
877         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
879 };
880 #define SHADERSTATICPARMS_COUNT 8
881
882 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
883 static int shaderstaticparms_count = 0;
884
885 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
886 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
887 qboolean R_CompileShader_CheckStaticParms(void)
888 {
889         static int r_compileshader_staticparms_save[1];
890         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
891         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
892
893         // detect all
894         if (r_glsl_saturation_redcompensate.integer)
895                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
896         if (r_glsl_vertextextureblend_usebothalphas.integer)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
898         if (r_shadow_glossexact.integer)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
900         if (r_glsl_postprocess.integer)
901         {
902                 if (r_glsl_postprocess_uservec1_enable.integer)
903                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
904                 if (r_glsl_postprocess_uservec2_enable.integer)
905                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
906                 if (r_glsl_postprocess_uservec3_enable.integer)
907                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
908                 if (r_glsl_postprocess_uservec4_enable.integer)
909                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
910         }
911         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
912                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
913         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
914 }
915
916 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
917         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
918                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
919         else \
920                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
921 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
922 {
923         shaderstaticparms_count = 0;
924
925         // emit all
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
934 }
935
936 /// information about each possible shader permutation
937 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
938 /// currently selected permutation
939 r_glsl_permutation_t *r_glsl_permutation;
940 /// storage for permutations linked in the hash table
941 memexpandablearray_t r_glsl_permutationarray;
942
943 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
944 {
945         //unsigned int hashdepth = 0;
946         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
947         r_glsl_permutation_t *p;
948         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
949         {
950                 if (p->mode == mode && p->permutation == permutation)
951                 {
952                         //if (hashdepth > 10)
953                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954                         return p;
955                 }
956                 //hashdepth++;
957         }
958         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
959         p->mode = mode;
960         p->permutation = permutation;
961         p->hashnext = r_glsl_permutationhash[mode][hashindex];
962         r_glsl_permutationhash[mode][hashindex] = p;
963         //if (hashdepth > 10)
964         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
965         return p;
966 }
967
968 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
969 {
970         char *shaderstring;
971         if (!filename || !filename[0])
972                 return NULL;
973         if (!strcmp(filename, "glsl/default.glsl"))
974         {
975                 if (!glslshaderstring)
976                 {
977                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978                         if (glslshaderstring)
979                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
980                         else
981                                 glslshaderstring = (char *)builtinshaderstring;
982                 }
983                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
984                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
985                 return shaderstring;
986         }
987         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
988         if (shaderstring)
989         {
990                 if (printfromdisknotice)
991                         Con_DPrintf("from disk %s... ", filename);
992                 return shaderstring;
993         }
994         return shaderstring;
995 }
996
997 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
998 {
999         int i;
1000         int sampler;
1001         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1002         char *vertexstring, *geometrystring, *fragmentstring;
1003         char permutationname[256];
1004         int vertstrings_count = 0;
1005         int geomstrings_count = 0;
1006         int fragstrings_count = 0;
1007         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1008         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1009         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1010
1011         if (p->compiled)
1012                 return;
1013         p->compiled = true;
1014         p->program = 0;
1015
1016         permutationname[0] = 0;
1017         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1018         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1019         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1020
1021         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1022
1023         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1024         if(vid.support.gl20shaders130)
1025         {
1026                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1027                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1028                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1029                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1030                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1031                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1032         }
1033
1034         // the first pretext is which type of shader to compile as
1035         // (later these will all be bound together as a program object)
1036         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1037         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1038         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1039
1040         // the second pretext is the mode (for example a light source)
1041         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1042         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1043         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1044         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1045
1046         // now add all the permutation pretexts
1047         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1048         {
1049                 if (permutation & (1<<i))
1050                 {
1051                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1052                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1053                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1055                 }
1056                 else
1057                 {
1058                         // keep line numbers correct
1059                         vertstrings_list[vertstrings_count++] = "\n";
1060                         geomstrings_list[geomstrings_count++] = "\n";
1061                         fragstrings_list[fragstrings_count++] = "\n";
1062                 }
1063         }
1064
1065         // add static parms
1066         R_CompileShader_AddStaticParms(mode, permutation);
1067         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1068         vertstrings_count += shaderstaticparms_count;
1069         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1070         geomstrings_count += shaderstaticparms_count;
1071         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1072         fragstrings_count += shaderstaticparms_count;
1073
1074         // now append the shader text itself
1075         vertstrings_list[vertstrings_count++] = vertexstring;
1076         geomstrings_list[geomstrings_count++] = geometrystring;
1077         fragstrings_list[fragstrings_count++] = fragmentstring;
1078
1079         // if any sources were NULL, clear the respective list
1080         if (!vertexstring)
1081                 vertstrings_count = 0;
1082         if (!geometrystring)
1083                 geomstrings_count = 0;
1084         if (!fragmentstring)
1085                 fragstrings_count = 0;
1086
1087         // compile the shader program
1088         if (vertstrings_count + geomstrings_count + fragstrings_count)
1089                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1090         if (p->program)
1091         {
1092                 CHECKGLERROR
1093                 qglUseProgram(p->program);CHECKGLERROR
1094                 // look up all the uniform variable names we care about, so we don't
1095                 // have to look them up every time we set them
1096
1097                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1098                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1099                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1100                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1101                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1102                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1103                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1104                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1105                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1106                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1107                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1108                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1109                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1110                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1111                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1112                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1113                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1114                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1115                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1116                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1117                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1118                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1119                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1120                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1121                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1122                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1123                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1124                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1125                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1126                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1127                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1128                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1129                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1130                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1131                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1132                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1133                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1134                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1135                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1136                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1137                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1138                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1139                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1140                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1141                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1142                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1143                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1144                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1145                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1146                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1147                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1148                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1149                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1150                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1151                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1152                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1153                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1154                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1155                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1156                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1157                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1158                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1159                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1160                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1161                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1162                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1163                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1164                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1165                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1166                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1167                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1168                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1169                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1170                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1171                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1172                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1173                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1174                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1175                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1176                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1177                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1178                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1179                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1180                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1181                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1182                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1183                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1184                 // initialize the samplers to refer to the texture units we use
1185                 p->tex_Texture_First = -1;
1186                 p->tex_Texture_Second = -1;
1187                 p->tex_Texture_GammaRamps = -1;
1188                 p->tex_Texture_Normal = -1;
1189                 p->tex_Texture_Color = -1;
1190                 p->tex_Texture_Gloss = -1;
1191                 p->tex_Texture_Glow = -1;
1192                 p->tex_Texture_SecondaryNormal = -1;
1193                 p->tex_Texture_SecondaryColor = -1;
1194                 p->tex_Texture_SecondaryGloss = -1;
1195                 p->tex_Texture_SecondaryGlow = -1;
1196                 p->tex_Texture_Pants = -1;
1197                 p->tex_Texture_Shirt = -1;
1198                 p->tex_Texture_FogHeightTexture = -1;
1199                 p->tex_Texture_FogMask = -1;
1200                 p->tex_Texture_Lightmap = -1;
1201                 p->tex_Texture_Deluxemap = -1;
1202                 p->tex_Texture_Attenuation = -1;
1203                 p->tex_Texture_Cube = -1;
1204                 p->tex_Texture_Refraction = -1;
1205                 p->tex_Texture_Reflection = -1;
1206                 p->tex_Texture_ShadowMap2D = -1;
1207                 p->tex_Texture_CubeProjection = -1;
1208                 p->tex_Texture_ScreenDepth = -1;
1209                 p->tex_Texture_ScreenNormalMap = -1;
1210                 p->tex_Texture_ScreenDiffuse = -1;
1211                 p->tex_Texture_ScreenSpecular = -1;
1212                 p->tex_Texture_ReflectMask = -1;
1213                 p->tex_Texture_ReflectCube = -1;
1214                 p->tex_Texture_BounceGrid = -1;
1215                 sampler = 0;
1216                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1217                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1218                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1219                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1220                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1221                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1222                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1223                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1226                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1227                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1228                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1229                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1230                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1231                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1232                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1233                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1234                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1235                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1236                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1237                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1238                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1239                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1242                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1243                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1244                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1245                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1246                 CHECKGLERROR
1247                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1248         }
1249         else
1250                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1251
1252         // free the strings
1253         if (vertexstring)
1254                 Mem_Free(vertexstring);
1255         if (geometrystring)
1256                 Mem_Free(geometrystring);
1257         if (fragmentstring)
1258                 Mem_Free(fragmentstring);
1259 }
1260
1261 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1262 {
1263         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1264         if (r_glsl_permutation != perm)
1265         {
1266                 r_glsl_permutation = perm;
1267                 if (!r_glsl_permutation->program)
1268                 {
1269                         if (!r_glsl_permutation->compiled)
1270                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1271                         if (!r_glsl_permutation->program)
1272                         {
1273                                 // remove features until we find a valid permutation
1274                                 int i;
1275                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1276                                 {
1277                                         // reduce i more quickly whenever it would not remove any bits
1278                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1279                                         if (!(permutation & j))
1280                                                 continue;
1281                                         permutation -= j;
1282                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1283                                         if (!r_glsl_permutation->compiled)
1284                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1285                                         if (r_glsl_permutation->program)
1286                                                 break;
1287                                 }
1288                                 if (i >= SHADERPERMUTATION_COUNT)
1289                                 {
1290                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1291                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1292                                         qglUseProgram(0);CHECKGLERROR
1293                                         return; // no bit left to clear, entire mode is broken
1294                                 }
1295                         }
1296                 }
1297                 CHECKGLERROR
1298                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1299         }
1300         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1301         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1302         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1303 }
1304
1305 #ifdef SUPPORTD3D
1306
1307 #ifdef SUPPORTD3D
1308 #include <d3d9.h>
1309 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1310 extern D3DCAPS9 vid_d3d9caps;
1311 #endif
1312
1313 struct r_hlsl_permutation_s;
1314 typedef struct r_hlsl_permutation_s
1315 {
1316         /// hash lookup data
1317         struct r_hlsl_permutation_s *hashnext;
1318         unsigned int mode;
1319         unsigned int permutation;
1320
1321         /// indicates if we have tried compiling this permutation already
1322         qboolean compiled;
1323         /// NULL if compilation failed
1324         IDirect3DVertexShader9 *vertexshader;
1325         IDirect3DPixelShader9 *pixelshader;
1326 }
1327 r_hlsl_permutation_t;
1328
1329 typedef enum D3DVSREGISTER_e
1330 {
1331         D3DVSREGISTER_TexMatrix = 0, // float4x4
1332         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1333         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1334         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1335         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1336         D3DVSREGISTER_ModelToLight = 20, // float4x4
1337         D3DVSREGISTER_EyePosition = 24,
1338         D3DVSREGISTER_FogPlane = 25,
1339         D3DVSREGISTER_LightDir = 26,
1340         D3DVSREGISTER_LightPosition = 27,
1341 }
1342 D3DVSREGISTER_t;
1343
1344 typedef enum D3DPSREGISTER_e
1345 {
1346         D3DPSREGISTER_Alpha = 0,
1347         D3DPSREGISTER_BloomBlur_Parameters = 1,
1348         D3DPSREGISTER_ClientTime = 2,
1349         D3DPSREGISTER_Color_Ambient = 3,
1350         D3DPSREGISTER_Color_Diffuse = 4,
1351         D3DPSREGISTER_Color_Specular = 5,
1352         D3DPSREGISTER_Color_Glow = 6,
1353         D3DPSREGISTER_Color_Pants = 7,
1354         D3DPSREGISTER_Color_Shirt = 8,
1355         D3DPSREGISTER_DeferredColor_Ambient = 9,
1356         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1357         D3DPSREGISTER_DeferredColor_Specular = 11,
1358         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1359         D3DPSREGISTER_DeferredMod_Specular = 13,
1360         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1361         D3DPSREGISTER_EyePosition = 15, // unused
1362         D3DPSREGISTER_FogColor = 16,
1363         D3DPSREGISTER_FogHeightFade = 17,
1364         D3DPSREGISTER_FogPlane = 18,
1365         D3DPSREGISTER_FogPlaneViewDist = 19,
1366         D3DPSREGISTER_FogRangeRecip = 20,
1367         D3DPSREGISTER_LightColor = 21,
1368         D3DPSREGISTER_LightDir = 22, // unused
1369         D3DPSREGISTER_LightPosition = 23,
1370         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1371         D3DPSREGISTER_PixelSize = 25,
1372         D3DPSREGISTER_ReflectColor = 26,
1373         D3DPSREGISTER_ReflectFactor = 27,
1374         D3DPSREGISTER_ReflectOffset = 28,
1375         D3DPSREGISTER_RefractColor = 29,
1376         D3DPSREGISTER_Saturation = 30,
1377         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1378         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1379         D3DPSREGISTER_ScreenToDepth = 33,
1380         D3DPSREGISTER_ShadowMap_Parameters = 34,
1381         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1382         D3DPSREGISTER_SpecularPower = 36,
1383         D3DPSREGISTER_UserVec1 = 37,
1384         D3DPSREGISTER_UserVec2 = 38,
1385         D3DPSREGISTER_UserVec3 = 39,
1386         D3DPSREGISTER_UserVec4 = 40,
1387         D3DPSREGISTER_ViewTintColor = 41,
1388         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1389         D3DPSREGISTER_BloomColorSubtract = 43,
1390         D3DPSREGISTER_ViewToLight = 44, // float4x4
1391         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1392         D3DPSREGISTER_NormalmapScrollBlend = 52,
1393         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1394         D3DPSREGISTER_OffsetMapping_Bias = 54,
1395         // next at 54
1396 }
1397 D3DPSREGISTER_t;
1398
1399 /// information about each possible shader permutation
1400 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1401 /// currently selected permutation
1402 r_hlsl_permutation_t *r_hlsl_permutation;
1403 /// storage for permutations linked in the hash table
1404 memexpandablearray_t r_hlsl_permutationarray;
1405
1406 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1407 {
1408         //unsigned int hashdepth = 0;
1409         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1410         r_hlsl_permutation_t *p;
1411         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1412         {
1413                 if (p->mode == mode && p->permutation == permutation)
1414                 {
1415                         //if (hashdepth > 10)
1416                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1417                         return p;
1418                 }
1419                 //hashdepth++;
1420         }
1421         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1422         p->mode = mode;
1423         p->permutation = permutation;
1424         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1425         r_hlsl_permutationhash[mode][hashindex] = p;
1426         //if (hashdepth > 10)
1427         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1428         return p;
1429 }
1430
1431 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1432 {
1433         char *shaderstring;
1434         if (!filename || !filename[0])
1435                 return NULL;
1436         if (!strcmp(filename, "hlsl/default.hlsl"))
1437         {
1438                 if (!hlslshaderstring)
1439                 {
1440                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1441                         if (hlslshaderstring)
1442                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1443                         else
1444                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1445                 }
1446                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1447                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1448                 return shaderstring;
1449         }
1450         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1451         if (shaderstring)
1452         {
1453                 if (printfromdisknotice)
1454                         Con_DPrintf("from disk %s... ", filename);
1455                 return shaderstring;
1456         }
1457         return shaderstring;
1458 }
1459
1460 #include <d3dx9.h>
1461 //#include <d3dx9shader.h>
1462 //#include <d3dx9mesh.h>
1463
1464 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1465 {
1466         DWORD *vsbin = NULL;
1467         DWORD *psbin = NULL;
1468         fs_offset_t vsbinsize;
1469         fs_offset_t psbinsize;
1470 //      IDirect3DVertexShader9 *vs = NULL;
1471 //      IDirect3DPixelShader9 *ps = NULL;
1472         ID3DXBuffer *vslog = NULL;
1473         ID3DXBuffer *vsbuffer = NULL;
1474         ID3DXConstantTable *vsconstanttable = NULL;
1475         ID3DXBuffer *pslog = NULL;
1476         ID3DXBuffer *psbuffer = NULL;
1477         ID3DXConstantTable *psconstanttable = NULL;
1478         int vsresult = 0;
1479         int psresult = 0;
1480         char temp[MAX_INPUTLINE];
1481         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1482         qboolean debugshader = gl_paranoid.integer != 0;
1483         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1484         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1485         if (!debugshader)
1486         {
1487                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1488                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1489         }
1490         if ((!vsbin && vertstring) || (!psbin && fragstring))
1491         {
1492                 const char* dllnames_d3dx9 [] =
1493                 {
1494                         "d3dx9_43.dll",
1495                         "d3dx9_42.dll",
1496                         "d3dx9_41.dll",
1497                         "d3dx9_40.dll",
1498                         "d3dx9_39.dll",
1499                         "d3dx9_38.dll",
1500                         "d3dx9_37.dll",
1501                         "d3dx9_36.dll",
1502                         "d3dx9_35.dll",
1503                         "d3dx9_34.dll",
1504                         "d3dx9_33.dll",
1505                         "d3dx9_32.dll",
1506                         "d3dx9_31.dll",
1507                         "d3dx9_30.dll",
1508                         "d3dx9_29.dll",
1509                         "d3dx9_28.dll",
1510                         "d3dx9_27.dll",
1511                         "d3dx9_26.dll",
1512                         "d3dx9_25.dll",
1513                         "d3dx9_24.dll",
1514                         NULL
1515                 };
1516                 dllhandle_t d3dx9_dll = NULL;
1517                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1518                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1519                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1520                 dllfunction_t d3dx9_dllfuncs[] =
1521                 {
1522                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1523                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1524                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1525                         {NULL, NULL}
1526                 };
1527                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1528                 {
1529                         DWORD shaderflags = 0;
1530                         if (debugshader)
1531                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1532                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1533                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1534                         if (vertstring && vertstring[0])
1535                         {
1536                                 if (debugshader)
1537                                 {
1538 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1539 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1540                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1541                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1542                                 }
1543                                 else
1544                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1545                                 if (vsbuffer)
1546                                 {
1547                                         vsbinsize = vsbuffer->GetBufferSize();
1548                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1549                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1550                                         vsbuffer->Release();
1551                                 }
1552                                 if (vslog)
1553                                 {
1554                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1555                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1556                                         vslog->Release();
1557                                 }
1558                         }
1559                         if (fragstring && fragstring[0])
1560                         {
1561                                 if (debugshader)
1562                                 {
1563 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1564 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1565                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1566                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1567                                 }
1568                                 else
1569                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1570                                 if (psbuffer)
1571                                 {
1572                                         psbinsize = psbuffer->GetBufferSize();
1573                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1574                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1575                                         psbuffer->Release();
1576                                 }
1577                                 if (pslog)
1578                                 {
1579                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1580                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1581                                         pslog->Release();
1582                                 }
1583                         }
1584                         Sys_UnloadLibrary(&d3dx9_dll);
1585                 }
1586                 else
1587                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1588         }
1589         if (vsbin && psbin)
1590         {
1591                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1592                 if (FAILED(vsresult))
1593                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1594                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1595                 if (FAILED(psresult))
1596                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1597         }
1598         // free the shader data
1599         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1600         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1601 }
1602
1603 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1604 {
1605         int i;
1606         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1607         int vertstring_length = 0;
1608         int geomstring_length = 0;
1609         int fragstring_length = 0;
1610         char *t;
1611         char *vertexstring, *geometrystring, *fragmentstring;
1612         char *vertstring, *geomstring, *fragstring;
1613         char permutationname[256];
1614         char cachename[256];
1615         int vertstrings_count = 0;
1616         int geomstrings_count = 0;
1617         int fragstrings_count = 0;
1618         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1619         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1620         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1621
1622         if (p->compiled)
1623                 return;
1624         p->compiled = true;
1625         p->vertexshader = NULL;
1626         p->pixelshader = NULL;
1627
1628         permutationname[0] = 0;
1629         cachename[0] = 0;
1630         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1631         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1632         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1633
1634         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1635         strlcat(cachename, "hlsl/", sizeof(cachename));
1636
1637         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1638         vertstrings_count = 0;
1639         geomstrings_count = 0;
1640         fragstrings_count = 0;
1641         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1642         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1643         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1644
1645         // the first pretext is which type of shader to compile as
1646         // (later these will all be bound together as a program object)
1647         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1648         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1649         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1650
1651         // the second pretext is the mode (for example a light source)
1652         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1653         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1654         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1655         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1656         strlcat(cachename, modeinfo->name, sizeof(cachename));
1657
1658         // now add all the permutation pretexts
1659         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1660         {
1661                 if (permutation & (1<<i))
1662                 {
1663                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1664                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1665                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1666                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1667                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1668                 }
1669                 else
1670                 {
1671                         // keep line numbers correct
1672                         vertstrings_list[vertstrings_count++] = "\n";
1673                         geomstrings_list[geomstrings_count++] = "\n";
1674                         fragstrings_list[fragstrings_count++] = "\n";
1675                 }
1676         }
1677
1678         // add static parms
1679         R_CompileShader_AddStaticParms(mode, permutation);
1680         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1681         vertstrings_count += shaderstaticparms_count;
1682         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683         geomstrings_count += shaderstaticparms_count;
1684         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1685         fragstrings_count += shaderstaticparms_count;
1686
1687         // replace spaces in the cachename with _ characters
1688         for (i = 0;cachename[i];i++)
1689                 if (cachename[i] == ' ')
1690                         cachename[i] = '_';
1691
1692         // now append the shader text itself
1693         vertstrings_list[vertstrings_count++] = vertexstring;
1694         geomstrings_list[geomstrings_count++] = geometrystring;
1695         fragstrings_list[fragstrings_count++] = fragmentstring;
1696
1697         // if any sources were NULL, clear the respective list
1698         if (!vertexstring)
1699                 vertstrings_count = 0;
1700         if (!geometrystring)
1701                 geomstrings_count = 0;
1702         if (!fragmentstring)
1703                 fragstrings_count = 0;
1704
1705         vertstring_length = 0;
1706         for (i = 0;i < vertstrings_count;i++)
1707                 vertstring_length += strlen(vertstrings_list[i]);
1708         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1709         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1710                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1711
1712         geomstring_length = 0;
1713         for (i = 0;i < geomstrings_count;i++)
1714                 geomstring_length += strlen(geomstrings_list[i]);
1715         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1716         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1717                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1718
1719         fragstring_length = 0;
1720         for (i = 0;i < fragstrings_count;i++)
1721                 fragstring_length += strlen(fragstrings_list[i]);
1722         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1723         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1724                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1725
1726         // try to load the cached shader, or generate one
1727         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1728
1729         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1730                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1731         else
1732                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1733
1734         // free the strings
1735         if (vertstring)
1736                 Mem_Free(vertstring);
1737         if (geomstring)
1738                 Mem_Free(geomstring);
1739         if (fragstring)
1740                 Mem_Free(fragstring);
1741         if (vertexstring)
1742                 Mem_Free(vertexstring);
1743         if (geometrystring)
1744                 Mem_Free(geometrystring);
1745         if (fragmentstring)
1746                 Mem_Free(fragmentstring);
1747 }
1748
1749 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1750 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1751 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);}
1752 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);}
1753 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);}
1754 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);}
1755
1756 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1757 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1758 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);}
1759 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);}
1760 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);}
1761 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);}
1762
1763 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1764 {
1765         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1766         if (r_hlsl_permutation != perm)
1767         {
1768                 r_hlsl_permutation = perm;
1769                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1770                 {
1771                         if (!r_hlsl_permutation->compiled)
1772                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1773                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1774                         {
1775                                 // remove features until we find a valid permutation
1776                                 int i;
1777                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1778                                 {
1779                                         // reduce i more quickly whenever it would not remove any bits
1780                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1781                                         if (!(permutation & j))
1782                                                 continue;
1783                                         permutation -= j;
1784                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1785                                         if (!r_hlsl_permutation->compiled)
1786                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1787                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1788                                                 break;
1789                                 }
1790                                 if (i >= SHADERPERMUTATION_COUNT)
1791                                 {
1792                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1793                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1794                                         return; // no bit left to clear, entire mode is broken
1795                                 }
1796                         }
1797                 }
1798                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1799                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1800         }
1801         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1802         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1803         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1804 }
1805 #endif
1806
1807 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1808 {
1809         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1810         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1811         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1812         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1813 }
1814
1815 void R_GLSL_Restart_f(void)
1816 {
1817         unsigned int i, limit;
1818         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1819                 Mem_Free(glslshaderstring);
1820         glslshaderstring = NULL;
1821         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1822                 Mem_Free(hlslshaderstring);
1823         hlslshaderstring = NULL;
1824         switch(vid.renderpath)
1825         {
1826         case RENDERPATH_D3D9:
1827 #ifdef SUPPORTD3D
1828                 {
1829                         r_hlsl_permutation_t *p;
1830                         r_hlsl_permutation = NULL;
1831                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1832                         for (i = 0;i < limit;i++)
1833                         {
1834                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1835                                 {
1836                                         if (p->vertexshader)
1837                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1838                                         if (p->pixelshader)
1839                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1840                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1841                                 }
1842                         }
1843                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1844                 }
1845 #endif
1846                 break;
1847         case RENDERPATH_D3D10:
1848                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1849                 break;
1850         case RENDERPATH_D3D11:
1851                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1852                 break;
1853         case RENDERPATH_GL20:
1854         case RENDERPATH_GLES2:
1855                 {
1856                         r_glsl_permutation_t *p;
1857                         r_glsl_permutation = NULL;
1858                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1859                         for (i = 0;i < limit;i++)
1860                         {
1861                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1862                                 {
1863                                         GL_Backend_FreeProgram(p->program);
1864                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1865                                 }
1866                         }
1867                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1868                 }
1869                 break;
1870         case RENDERPATH_GL11:
1871         case RENDERPATH_GL13:
1872         case RENDERPATH_GLES1:
1873                 break;
1874         case RENDERPATH_SOFT:
1875                 break;
1876         }
1877 }
1878
1879 void R_GLSL_DumpShader_f(void)
1880 {
1881         int i;
1882         qfile_t *file;
1883
1884         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1885         if (file)
1886         {
1887                 FS_Print(file, "/* The engine may define the following macros:\n");
1888                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889                 for (i = 0;i < SHADERMODE_COUNT;i++)
1890                         FS_Print(file, glslshadermodeinfo[i].pretext);
1891                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892                         FS_Print(file, shaderpermutationinfo[i].pretext);
1893                 FS_Print(file, "*/\n");
1894                 FS_Print(file, builtinshaderstring);
1895                 FS_Close(file);
1896                 Con_Printf("glsl/default.glsl written\n");
1897         }
1898         else
1899                 Con_Printf("failed to write to glsl/default.glsl\n");
1900
1901         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1902         if (file)
1903         {
1904                 FS_Print(file, "/* The engine may define the following macros:\n");
1905                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1906                 for (i = 0;i < SHADERMODE_COUNT;i++)
1907                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1908                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1909                         FS_Print(file, shaderpermutationinfo[i].pretext);
1910                 FS_Print(file, "*/\n");
1911                 FS_Print(file, builtinhlslshaderstring);
1912                 FS_Close(file);
1913                 Con_Printf("hlsl/default.hlsl written\n");
1914         }
1915         else
1916                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1917 }
1918
1919 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1920 {
1921         unsigned int permutation = 0;
1922         if (r_trippy.integer && !notrippy)
1923                 permutation |= SHADERPERMUTATION_TRIPPY;
1924         permutation |= SHADERPERMUTATION_VIEWTINT;
1925         if (first)
1926                 permutation |= SHADERPERMUTATION_DIFFUSE;
1927         if (second)
1928                 permutation |= SHADERPERMUTATION_SPECULAR;
1929         if (texturemode == GL_MODULATE)
1930                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1931         else if (texturemode == GL_ADD)
1932                 permutation |= SHADERPERMUTATION_GLOW;
1933         else if (texturemode == GL_DECAL)
1934                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1935         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1936                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1937         if (!second)
1938                 texturemode = GL_MODULATE;
1939         if (vid.allowalphatocoverage)
1940                 GL_AlphaToCoverage(false);
1941         switch (vid.renderpath)
1942         {
1943         case RENDERPATH_D3D9:
1944 #ifdef SUPPORTD3D
1945                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1946                 R_Mesh_TexBind(GL20TU_FIRST , first );
1947                 R_Mesh_TexBind(GL20TU_SECOND, second);
1948                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1949                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1950 #endif
1951                 break;
1952         case RENDERPATH_D3D10:
1953                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1954                 break;
1955         case RENDERPATH_D3D11:
1956                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_GL20:
1959         case RENDERPATH_GLES2:
1960                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1961                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1962                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1963                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1964                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1965                 break;
1966         case RENDERPATH_GL13:
1967         case RENDERPATH_GLES1:
1968                 R_Mesh_TexBind(0, first );
1969                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1970                 R_Mesh_TexBind(1, second);
1971                 if (second)
1972                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1973                 break;
1974         case RENDERPATH_GL11:
1975                 R_Mesh_TexBind(0, first );
1976                 break;
1977         case RENDERPATH_SOFT:
1978                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1979                 R_Mesh_TexBind(GL20TU_FIRST , first );
1980                 R_Mesh_TexBind(GL20TU_SECOND, second);
1981                 break;
1982         }
1983 }
1984
1985 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1986 {
1987         unsigned int permutation = 0;
1988         if (r_trippy.integer && !notrippy)
1989                 permutation |= SHADERPERMUTATION_TRIPPY;
1990         if (vid.allowalphatocoverage)
1991                 GL_AlphaToCoverage(false);
1992         switch (vid.renderpath)
1993         {
1994         case RENDERPATH_D3D9:
1995 #ifdef SUPPORTD3D
1996                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1997 #endif
1998                 break;
1999         case RENDERPATH_D3D10:
2000                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2001                 break;
2002         case RENDERPATH_D3D11:
2003                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2004                 break;
2005         case RENDERPATH_GL20:
2006         case RENDERPATH_GLES2:
2007                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2008                 break;
2009         case RENDERPATH_GL13:
2010         case RENDERPATH_GLES1:
2011                 R_Mesh_TexBind(0, 0);
2012                 R_Mesh_TexBind(1, 0);
2013                 break;
2014         case RENDERPATH_GL11:
2015                 R_Mesh_TexBind(0, 0);
2016                 break;
2017         case RENDERPATH_SOFT:
2018                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2019                 break;
2020         }
2021 }
2022
2023 void R_SetupShader_ShowDepth(qboolean notrippy)
2024 {
2025         int permutation = 0;
2026         if (r_trippy.integer && !notrippy)
2027                 permutation |= SHADERPERMUTATION_TRIPPY;
2028         if (vid.allowalphatocoverage)
2029                 GL_AlphaToCoverage(false);
2030         switch (vid.renderpath)
2031         {
2032         case RENDERPATH_D3D9:
2033 #ifdef SUPPORTHLSL
2034                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2035 #endif
2036                 break;
2037         case RENDERPATH_D3D10:
2038                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2039                 break;
2040         case RENDERPATH_D3D11:
2041                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2042                 break;
2043         case RENDERPATH_GL20:
2044         case RENDERPATH_GLES2:
2045                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2046                 break;
2047         case RENDERPATH_GL13:
2048         case RENDERPATH_GLES1:
2049                 break;
2050         case RENDERPATH_GL11:
2051                 break;
2052         case RENDERPATH_SOFT:
2053                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2054                 break;
2055         }
2056 }
2057
2058 extern qboolean r_shadow_usingdeferredprepass;
2059 extern cvar_t r_shadow_deferred_8bitrange;
2060 extern rtexture_t *r_shadow_attenuationgradienttexture;
2061 extern rtexture_t *r_shadow_attenuation2dtexture;
2062 extern rtexture_t *r_shadow_attenuation3dtexture;
2063 extern qboolean r_shadow_usingshadowmap2d;
2064 extern qboolean r_shadow_usingshadowmaportho;
2065 extern float r_shadow_shadowmap_texturescale[2];
2066 extern float r_shadow_shadowmap_parameters[4];
2067 extern qboolean r_shadow_shadowmapvsdct;
2068 extern qboolean r_shadow_shadowmapsampler;
2069 extern int r_shadow_shadowmappcf;
2070 extern rtexture_t *r_shadow_shadowmap2dtexture;
2071 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2072 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2073 extern matrix4x4_t r_shadow_shadowmapmatrix;
2074 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2075 extern int r_shadow_prepass_width;
2076 extern int r_shadow_prepass_height;
2077 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2078 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2079 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2080 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2081 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2082
2083 #define BLENDFUNC_ALLOWS_COLORMOD      1
2084 #define BLENDFUNC_ALLOWS_FOG           2
2085 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2086 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2087 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2088 static int R_BlendFuncFlags(int src, int dst)
2089 {
2090         int r = 0;
2091
2092         // a blendfunc allows colormod if:
2093         // a) it can never keep the destination pixel invariant, or
2094         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2095         // this is to prevent unintended side effects from colormod
2096
2097         // a blendfunc allows fog if:
2098         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2099         // this is to prevent unintended side effects from fog
2100
2101         // these checks are the output of fogeval.pl
2102
2103         r |= BLENDFUNC_ALLOWS_COLORMOD;
2104         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2108         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2110         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2111         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2112         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2113         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2114         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2115         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2118         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2120         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2121         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2122         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2123         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2124         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2125
2126         return r;
2127 }
2128
2129 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)
2130 {
2131         // select a permutation of the lighting shader appropriate to this
2132         // combination of texture, entity, light source, and fogging, only use the
2133         // minimum features necessary to avoid wasting rendering time in the
2134         // fragment shader on features that are not being used
2135         unsigned int permutation = 0;
2136         unsigned int mode = 0;
2137         int blendfuncflags;
2138         static float dummy_colormod[3] = {1, 1, 1};
2139         float *colormod = rsurface.colormod;
2140         float m16f[16];
2141         matrix4x4_t tempmatrix;
2142         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2143         if (r_trippy.integer && !notrippy)
2144                 permutation |= SHADERPERMUTATION_TRIPPY;
2145         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2146                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2147         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2148                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2149         if (rsurfacepass == RSURFPASS_BACKGROUND)
2150         {
2151                 // distorted background
2152                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2153                 {
2154                         mode = SHADERMODE_WATER;
2155                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2156                         {
2157                                 // this is the right thing to do for wateralpha
2158                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2159                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2160                         }
2161                         else
2162                         {
2163                                 // this is the right thing to do for entity alpha
2164                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2165                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2166                         }
2167                 }
2168                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2169                 {
2170                         mode = SHADERMODE_REFRACTION;
2171                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2172                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2173                 }
2174                 else
2175                 {
2176                         mode = SHADERMODE_GENERIC;
2177                         permutation |= SHADERPERMUTATION_DIFFUSE;
2178                         GL_BlendFunc(GL_ONE, GL_ZERO);
2179                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2180                 }
2181                 if (vid.allowalphatocoverage)
2182                         GL_AlphaToCoverage(false);
2183         }
2184         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2185         {
2186                 if (r_glsl_offsetmapping.integer)
2187                 {
2188                         switch(rsurface.texture->offsetmapping)
2189                         {
2190                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2191                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2192                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2193                         case OFFSETMAPPING_OFF: break;
2194                         }
2195                 }
2196                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2197                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2198                 // normalmap (deferred prepass), may use alpha test on diffuse
2199                 mode = SHADERMODE_DEFERREDGEOMETRY;
2200                 GL_BlendFunc(GL_ONE, GL_ZERO);
2201                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2202                 if (vid.allowalphatocoverage)
2203                         GL_AlphaToCoverage(false);
2204         }
2205         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2206         {
2207                 if (r_glsl_offsetmapping.integer)
2208                 {
2209                         switch(rsurface.texture->offsetmapping)
2210                         {
2211                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2212                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2213                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2214                         case OFFSETMAPPING_OFF: break;
2215                         }
2216                 }
2217                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2218                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2219                 // light source
2220                 mode = SHADERMODE_LIGHTSOURCE;
2221                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2222                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2223                 if (diffusescale > 0)
2224                         permutation |= SHADERPERMUTATION_DIFFUSE;
2225                 if (specularscale > 0)
2226                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2227                 if (r_refdef.fogenabled)
2228                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2229                 if (rsurface.texture->colormapping)
2230                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2231                 if (r_shadow_usingshadowmap2d)
2232                 {
2233                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2234                         if(r_shadow_shadowmapvsdct)
2235                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2236
2237                         if (r_shadow_shadowmapsampler)
2238                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2239                         if (r_shadow_shadowmappcf > 1)
2240                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2241                         else if (r_shadow_shadowmappcf)
2242                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2243                 }
2244                 if (rsurface.texture->reflectmasktexture)
2245                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2246                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2247                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2248                 if (vid.allowalphatocoverage)
2249                         GL_AlphaToCoverage(false);
2250         }
2251         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2252         {
2253                 if (r_glsl_offsetmapping.integer)
2254                 {
2255                         switch(rsurface.texture->offsetmapping)
2256                         {
2257                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2258                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2259                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2260                         case OFFSETMAPPING_OFF: break;
2261                         }
2262                 }
2263                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2264                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2265                 // unshaded geometry (fullbright or ambient model lighting)
2266                 mode = SHADERMODE_FLATCOLOR;
2267                 ambientscale = diffusescale = specularscale = 0;
2268                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2269                         permutation |= SHADERPERMUTATION_GLOW;
2270                 if (r_refdef.fogenabled)
2271                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2272                 if (rsurface.texture->colormapping)
2273                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2274                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2275                 {
2276                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2277                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2278
2279                         if (r_shadow_shadowmapsampler)
2280                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2281                         if (r_shadow_shadowmappcf > 1)
2282                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2283                         else if (r_shadow_shadowmappcf)
2284                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2285                 }
2286                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2287                         permutation |= SHADERPERMUTATION_REFLECTION;
2288                 if (rsurface.texture->reflectmasktexture)
2289                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2290                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2292                 // when using alphatocoverage, we don't need alphakill
2293                 if (vid.allowalphatocoverage)
2294                 {
2295                         if (r_transparent_alphatocoverage.integer)
2296                         {
2297                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2298                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2299                         }
2300                         else
2301                                 GL_AlphaToCoverage(false);
2302                 }
2303         }
2304         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2305         {
2306                 if (r_glsl_offsetmapping.integer)
2307                 {
2308                         switch(rsurface.texture->offsetmapping)
2309                         {
2310                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2311                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2312                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2313                         case OFFSETMAPPING_OFF: break;
2314                         }
2315                 }
2316                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2317                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2318                 // directional model lighting
2319                 mode = SHADERMODE_LIGHTDIRECTION;
2320                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2321                         permutation |= SHADERPERMUTATION_GLOW;
2322                 permutation |= SHADERPERMUTATION_DIFFUSE;
2323                 if (specularscale > 0)
2324                         permutation |= SHADERPERMUTATION_SPECULAR;
2325                 if (r_refdef.fogenabled)
2326                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2327                 if (rsurface.texture->colormapping)
2328                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2329                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2330                 {
2331                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2332                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2333
2334                         if (r_shadow_shadowmapsampler)
2335                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2336                         if (r_shadow_shadowmappcf > 1)
2337                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2338                         else if (r_shadow_shadowmappcf)
2339                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2340                 }
2341                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2342                         permutation |= SHADERPERMUTATION_REFLECTION;
2343                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2344                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2345                 if (rsurface.texture->reflectmasktexture)
2346                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2347                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2348                 {
2349                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2350                         if (r_shadow_bouncegriddirectional)
2351                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2352                 }
2353                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2354                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2355                 // when using alphatocoverage, we don't need alphakill
2356                 if (vid.allowalphatocoverage)
2357                 {
2358                         if (r_transparent_alphatocoverage.integer)
2359                         {
2360                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2361                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2362                         }
2363                         else
2364                                 GL_AlphaToCoverage(false);
2365                 }
2366         }
2367         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2368         {
2369                 if (r_glsl_offsetmapping.integer)
2370                 {
2371                         switch(rsurface.texture->offsetmapping)
2372                         {
2373                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2374                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2375                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2376                         case OFFSETMAPPING_OFF: break;
2377                         }
2378                 }
2379                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2380                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2381                 // ambient model lighting
2382                 mode = SHADERMODE_LIGHTDIRECTION;
2383                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2384                         permutation |= SHADERPERMUTATION_GLOW;
2385                 if (r_refdef.fogenabled)
2386                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2387                 if (rsurface.texture->colormapping)
2388                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2389                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2390                 {
2391                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2392                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2393
2394                         if (r_shadow_shadowmapsampler)
2395                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2396                         if (r_shadow_shadowmappcf > 1)
2397                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2398                         else if (r_shadow_shadowmappcf)
2399                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2402                         permutation |= SHADERPERMUTATION_REFLECTION;
2403                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2404                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2405                 if (rsurface.texture->reflectmasktexture)
2406                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2407                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2408                 {
2409                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2410                         if (r_shadow_bouncegriddirectional)
2411                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2412                 }
2413                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 // when using alphatocoverage, we don't need alphakill
2416                 if (vid.allowalphatocoverage)
2417                 {
2418                         if (r_transparent_alphatocoverage.integer)
2419                         {
2420                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2421                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2422                         }
2423                         else
2424                                 GL_AlphaToCoverage(false);
2425                 }
2426         }
2427         else
2428         {
2429                 if (r_glsl_offsetmapping.integer)
2430                 {
2431                         switch(rsurface.texture->offsetmapping)
2432                         {
2433                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2434                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2435                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436                         case OFFSETMAPPING_OFF: break;
2437                         }
2438                 }
2439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2440                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2441                 // lightmapped wall
2442                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2443                         permutation |= SHADERPERMUTATION_GLOW;
2444                 if (r_refdef.fogenabled)
2445                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2446                 if (rsurface.texture->colormapping)
2447                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2448                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2449                 {
2450                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2451                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2452
2453                         if (r_shadow_shadowmapsampler)
2454                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2455                         if (r_shadow_shadowmappcf > 1)
2456                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2457                         else if (r_shadow_shadowmappcf)
2458                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2459                 }
2460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2461                         permutation |= SHADERPERMUTATION_REFLECTION;
2462                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2463                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2464                 if (rsurface.texture->reflectmasktexture)
2465                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2466                 if (FAKELIGHT_ENABLED)
2467                 {
2468                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2469                         mode = SHADERMODE_FAKELIGHT;
2470                         permutation |= SHADERPERMUTATION_DIFFUSE;
2471                         if (specularscale > 0)
2472                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2473                 }
2474                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2475                 {
2476                         // deluxemapping (light direction texture)
2477                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2479                         else
2480                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2481                         permutation |= SHADERPERMUTATION_DIFFUSE;
2482                         if (specularscale > 0)
2483                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2484                 }
2485                 else if (r_glsl_deluxemapping.integer >= 2)
2486                 {
2487                         // fake deluxemapping (uniform light direction in tangentspace)
2488                         if (rsurface.uselightmaptexture)
2489                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2490                         else
2491                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2492                         permutation |= SHADERPERMUTATION_DIFFUSE;
2493                         if (specularscale > 0)
2494                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2495                 }
2496                 else if (rsurface.uselightmaptexture)
2497                 {
2498                         // ordinary lightmapping (q1bsp, q3bsp)
2499                         mode = SHADERMODE_LIGHTMAP;
2500                 }
2501                 else
2502                 {
2503                         // ordinary vertex coloring (q3bsp)
2504                         mode = SHADERMODE_VERTEXCOLOR;
2505                 }
2506                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2507                 {
2508                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2509                         if (r_shadow_bouncegriddirectional)
2510                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2511                 }
2512                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2513                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2514                 // when using alphatocoverage, we don't need alphakill
2515                 if (vid.allowalphatocoverage)
2516                 {
2517                         if (r_transparent_alphatocoverage.integer)
2518                         {
2519                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2520                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2521                         }
2522                         else
2523                                 GL_AlphaToCoverage(false);
2524                 }
2525         }
2526         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2527                 colormod = dummy_colormod;
2528         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2529                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2530         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2531                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2532         switch(vid.renderpath)
2533         {
2534         case RENDERPATH_D3D9:
2535 #ifdef SUPPORTD3D
2536                 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);
2537                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2538                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2539                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2540                 if (mode == SHADERMODE_LIGHTSOURCE)
2541                 {
2542                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2543                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2544                 }
2545                 else
2546                 {
2547                         if (mode == SHADERMODE_LIGHTDIRECTION)
2548                         {
2549                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2550                         }
2551                 }
2552                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2553                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2554                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2555                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2556                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2557
2558                 if (mode == SHADERMODE_LIGHTSOURCE)
2559                 {
2560                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2563                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2564                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2565
2566                         // additive passes are only darkened by fog, not tinted
2567                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2568                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2569                 }
2570                 else
2571                 {
2572                         if (mode == SHADERMODE_FLATCOLOR)
2573                         {
2574                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2575                         }
2576                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2577                         {
2578                                 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]);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2580                                 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);
2581                                 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);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2585                         }
2586                         else
2587                         {
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2590                                 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);
2591                                 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);
2592                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2593                         }
2594                         // additive passes are only darkened by fog, not tinted
2595                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2597                         else
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2599                         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);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2602                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2603                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2605                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2606                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2607                         if (mode == SHADERMODE_WATER)
2608                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2609                 }
2610                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2611                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2612                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2613                 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));
2614                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2615                 if (rsurface.texture->pantstexture)
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2617                 else
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2619                 if (rsurface.texture->shirttexture)
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2621                 else
2622                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2623                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2625                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2626                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2627                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2628                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2629                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2630                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2631                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2632                         );
2633                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer)
2634                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias / 255)
2635                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2636                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2637
2638                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2639                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2640                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2641                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2643                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2645                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2646                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2647                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2648                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2649                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2650                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2651                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2652                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2653                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2654                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2655                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2656                 {
2657                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2658                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2659                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2660                 }
2661                 else
2662                 {
2663                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2664                 }
2665 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2666 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2667                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2668                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2669                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2670                 {
2671                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2672                         if (rsurface.rtlight)
2673                         {
2674                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2675                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2676                         }
2677                 }
2678 #endif
2679                 break;
2680         case RENDERPATH_D3D10:
2681                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2682                 break;
2683         case RENDERPATH_D3D11:
2684                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2685                 break;
2686         case RENDERPATH_GL20:
2687         case RENDERPATH_GLES2:
2688                 if (!vid.useinterleavedarrays)
2689                 {
2690                         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);
2691                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2692                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2695                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2696                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2697                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2698                 }
2699                 else
2700                 {
2701                         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);
2702                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2703                 }
2704                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2705                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2706                 if (mode == SHADERMODE_LIGHTSOURCE)
2707                 {
2708                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2709                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2710                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2711                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2712                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2713                         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);
2714         
2715                         // additive passes are only darkened by fog, not tinted
2716                         if (r_glsl_permutation->loc_FogColor >= 0)
2717                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2718                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2719                 }
2720                 else
2721                 {
2722                         if (mode == SHADERMODE_FLATCOLOR)
2723                         {
2724                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2725                         }
2726                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2727                         {
2728                                 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]);
2729                                 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]);
2730                                 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);
2731                                 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);
2732                                 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);
2733                                 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]);
2734                                 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]);
2735                         }
2736                         else
2737                         {
2738                                 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]);
2739                                 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]);
2740                                 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);
2741                                 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);
2742                                 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);
2743                         }
2744                         // additive passes are only darkened by fog, not tinted
2745                         if (r_glsl_permutation->loc_FogColor >= 0)
2746                         {
2747                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2748                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2749                                 else
2750                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2751                         }
2752                         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);
2753                         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]);
2754                         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]);
2755                         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]);
2756                         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]);
2757                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2758                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2759                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2760                         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]);
2761                 }
2762                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2763                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2764                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2765                 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]);
2766                 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]);
2767
2768                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2769                 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));
2770                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2771                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2772                 {
2773                         if (rsurface.texture->pantstexture)
2774                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2775                         else
2776                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2777                 }
2778                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2779                 {
2780                         if (rsurface.texture->shirttexture)
2781                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2782                         else
2783                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2784                 }
2785                 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]);
2786                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2787                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2788                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2789                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2790                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2791                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2792                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2793                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2794                         );
2795                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2796                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias / 255);
2797                 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]);
2798                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2799                 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);}
2800                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2801
2802                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2803                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2804                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2805                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2806                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2807                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2808                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2810                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2811                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2812                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2813                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2814                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2815                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2816                 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);
2817                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2818                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2819                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2820                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2821                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2822                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2823                 {
2824                         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);
2825                         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);
2826                         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);
2827                 }
2828                 else
2829                 {
2830                         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);
2831                 }
2832                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2833                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2834                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2835                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2836                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2837                 {
2838                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2839                         if (rsurface.rtlight)
2840                         {
2841                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2842                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2843                         }
2844                 }
2845                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2846                 CHECKGLERROR
2847                 break;
2848         case RENDERPATH_GL11:
2849         case RENDERPATH_GL13:
2850         case RENDERPATH_GLES1:
2851                 break;
2852         case RENDERPATH_SOFT:
2853                 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);
2854                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2855                 R_SetupShader_SetPermutationSoft(mode, permutation);
2856                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2857                 if (mode == SHADERMODE_LIGHTSOURCE)
2858                 {
2859                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2861                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2862                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2864                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2865         
2866                         // additive passes are only darkened by fog, not tinted
2867                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2868                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2869                 }
2870                 else
2871                 {
2872                         if (mode == SHADERMODE_FLATCOLOR)
2873                         {
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2875                         }
2876                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2877                         {
2878                                 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]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2880                                 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);
2881                                 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);
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2883                                 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]);
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2885                         }
2886                         else
2887                         {
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2890                                 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);
2891                                 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);
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2893                         }
2894                         // additive passes are only darkened by fog, not tinted
2895                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2896                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2897                         else
2898                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2899                         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);
2900                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2901                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2902                         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]);
2903                         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]);
2904                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2905                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2906                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2907                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2908                 }
2909                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2910                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2911                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2912                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2913                 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]);
2914
2915                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2916                 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));
2917                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2918                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2919                 {
2920                         if (rsurface.texture->pantstexture)
2921                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2922                         else
2923                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2924                 }
2925                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2926                 {
2927                         if (rsurface.texture->shirttexture)
2928                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2929                         else
2930                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2931                 }
2932                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2933                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2934                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2935                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2936                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2937                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2938                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2939                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2940                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2941                         );
2942                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2943                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias / 255);
2944                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2945                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2946
2947                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2948                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2949                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2950                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2952                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2953                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2954                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2955                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2956                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2957                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2958                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2959                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2960                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2961                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2962                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2963                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2964                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2965                 {
2966                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2967                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2968                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2969                 }
2970                 else
2971                 {
2972                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2973                 }
2974 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2975 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2976                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2977                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2978                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2979                 {
2980                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2981                         if (rsurface.rtlight)
2982                         {
2983                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2984                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2985                         }
2986                 }
2987                 break;
2988         }
2989 }
2990
2991 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2992 {
2993         // select a permutation of the lighting shader appropriate to this
2994         // combination of texture, entity, light source, and fogging, only use the
2995         // minimum features necessary to avoid wasting rendering time in the
2996         // fragment shader on features that are not being used
2997         unsigned int permutation = 0;
2998         unsigned int mode = 0;
2999         const float *lightcolorbase = rtlight->currentcolor;
3000         float ambientscale = rtlight->ambientscale;
3001         float diffusescale = rtlight->diffusescale;
3002         float specularscale = rtlight->specularscale;
3003         // this is the location of the light in view space
3004         vec3_t viewlightorigin;
3005         // this transforms from view space (camera) to light space (cubemap)
3006         matrix4x4_t viewtolight;
3007         matrix4x4_t lighttoview;
3008         float viewtolight16f[16];
3009         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3010         // light source
3011         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3012         if (rtlight->currentcubemap != r_texture_whitecube)
3013                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3014         if (diffusescale > 0)
3015                 permutation |= SHADERPERMUTATION_DIFFUSE;
3016         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3017                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3018         if (r_shadow_usingshadowmap2d)
3019         {
3020                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3021                 if (r_shadow_shadowmapvsdct)
3022                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3023
3024                 if (r_shadow_shadowmapsampler)
3025                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3026                 if (r_shadow_shadowmappcf > 1)
3027                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3028                 else if (r_shadow_shadowmappcf)
3029                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3030         }
3031         if (vid.allowalphatocoverage)
3032                 GL_AlphaToCoverage(false);
3033         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3034         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3035         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3036         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3037         switch(vid.renderpath)
3038         {
3039         case RENDERPATH_D3D9:
3040 #ifdef SUPPORTD3D
3041                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3042                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3043                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3044                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3045                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3046                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3047                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3048                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3049                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3050                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3051                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3052
3053                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3054                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3055                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3056                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3057                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3058                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3059 #endif
3060                 break;
3061         case RENDERPATH_D3D10:
3062                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3063                 break;
3064         case RENDERPATH_D3D11:
3065                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3066                 break;
3067         case RENDERPATH_GL20:
3068         case RENDERPATH_GLES2:
3069                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3070                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3071                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3072                 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);
3073                 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);
3074                 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);
3075                 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]);
3076                 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]);
3077                 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) - 1.0f);
3078                 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]);
3079                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3080
3081                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3082                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3083                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3084                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3085                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3086                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3087                 break;
3088         case RENDERPATH_GL11:
3089         case RENDERPATH_GL13:
3090         case RENDERPATH_GLES1:
3091                 break;
3092         case RENDERPATH_SOFT:
3093                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3094                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3095                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3096                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3097                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3098                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3099                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3100                 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]);
3101                 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) - 1.0f);
3102                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3103                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3104
3105                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3106                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3107                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3108                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3109                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3110                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3111                 break;
3112         }
3113 }
3114
3115 #define SKINFRAME_HASH 1024
3116
3117 typedef struct
3118 {
3119         int loadsequence; // incremented each level change
3120         memexpandablearray_t array;
3121         skinframe_t *hash[SKINFRAME_HASH];
3122 }
3123 r_skinframe_t;
3124 r_skinframe_t r_skinframe;
3125
3126 void R_SkinFrame_PrepareForPurge(void)
3127 {
3128         r_skinframe.loadsequence++;
3129         // wrap it without hitting zero
3130         if (r_skinframe.loadsequence >= 200)
3131                 r_skinframe.loadsequence = 1;
3132 }
3133
3134 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3135 {
3136         if (!skinframe)
3137                 return;
3138         // mark the skinframe as used for the purging code
3139         skinframe->loadsequence = r_skinframe.loadsequence;
3140 }
3141
3142 void R_SkinFrame_Purge(void)
3143 {
3144         int i;
3145         skinframe_t *s;
3146         for (i = 0;i < SKINFRAME_HASH;i++)
3147         {
3148                 for (s = r_skinframe.hash[i];s;s = s->next)
3149                 {
3150                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3151                         {
3152                                 if (s->merged == s->base)
3153                                         s->merged = NULL;
3154                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3155                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3156                                 R_PurgeTexture(s->merged);s->merged = NULL;
3157                                 R_PurgeTexture(s->base  );s->base   = NULL;
3158                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3159                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3160                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3161                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3162                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3163                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3164                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3165                                 s->loadsequence = 0;
3166                         }
3167                 }
3168         }
3169 }
3170
3171 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3172         skinframe_t *item;
3173         char basename[MAX_QPATH];
3174
3175         Image_StripImageExtension(name, basename, sizeof(basename));
3176
3177         if( last == NULL ) {
3178                 int hashindex;
3179                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3180                 item = r_skinframe.hash[hashindex];
3181         } else {
3182                 item = last->next;
3183         }
3184
3185         // linearly search through the hash bucket
3186         for( ; item ; item = item->next ) {
3187                 if( !strcmp( item->basename, basename ) ) {
3188                         return item;
3189                 }
3190         }
3191         return NULL;
3192 }
3193
3194 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3195 {
3196         skinframe_t *item;
3197         int hashindex;
3198         char basename[MAX_QPATH];
3199
3200         Image_StripImageExtension(name, basename, sizeof(basename));
3201
3202         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3203         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3204                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3205                         break;
3206
3207         if (!item) {
3208                 rtexture_t *dyntexture;
3209                 // check whether its a dynamic texture
3210                 dyntexture = CL_GetDynTexture( basename );
3211                 if (!add && !dyntexture)
3212                         return NULL;
3213                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3214                 memset(item, 0, sizeof(*item));
3215                 strlcpy(item->basename, basename, sizeof(item->basename));
3216                 item->base = dyntexture; // either NULL or dyntexture handle
3217                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3218                 item->comparewidth = comparewidth;
3219                 item->compareheight = compareheight;
3220                 item->comparecrc = comparecrc;
3221                 item->next = r_skinframe.hash[hashindex];
3222                 r_skinframe.hash[hashindex] = item;
3223         }
3224         else if (textureflags & TEXF_FORCE_RELOAD)
3225         {
3226                 rtexture_t *dyntexture;
3227                 // check whether its a dynamic texture
3228                 dyntexture = CL_GetDynTexture( basename );
3229                 if (!add && !dyntexture)
3230                         return NULL;
3231                 if (item->merged == item->base)
3232                         item->merged = NULL;
3233                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3234                 R_PurgeTexture(item->stain );item->stain  = NULL;
3235                 R_PurgeTexture(item->merged);item->merged = NULL;
3236                 R_PurgeTexture(item->base  );item->base   = NULL;
3237                 R_PurgeTexture(item->pants );item->pants  = NULL;
3238                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3239                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3240                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3241                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3242                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3243         R_PurgeTexture(item->reflect);item->reflect = NULL;
3244                 item->loadsequence = 0;
3245         }
3246         else if( item->base == NULL )
3247         {
3248                 rtexture_t *dyntexture;
3249                 // check whether its a dynamic texture
3250                 // 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]
3251                 dyntexture = CL_GetDynTexture( basename );
3252                 item->base = dyntexture; // either NULL or dyntexture handle
3253         }
3254
3255         R_SkinFrame_MarkUsed(item);
3256         return item;
3257 }
3258
3259 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3260         { \
3261                 unsigned long long avgcolor[5], wsum; \
3262                 int pix, comp, w; \
3263                 avgcolor[0] = 0; \
3264                 avgcolor[1] = 0; \
3265                 avgcolor[2] = 0; \
3266                 avgcolor[3] = 0; \
3267                 avgcolor[4] = 0; \
3268                 wsum = 0; \
3269                 for(pix = 0; pix < cnt; ++pix) \
3270                 { \
3271                         w = 0; \
3272                         for(comp = 0; comp < 3; ++comp) \
3273                                 w += getpixel; \
3274                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3275                         { \
3276                                 ++wsum; \
3277                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3278                                 w = getpixel; \
3279                                 for(comp = 0; comp < 3; ++comp) \
3280                                         avgcolor[comp] += getpixel * w; \
3281                                 avgcolor[3] += w; \
3282                         } \
3283                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3284                         avgcolor[4] += getpixel; \
3285                 } \
3286                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3287                         avgcolor[3] = 1; \
3288                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3289                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3290                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3291                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3292         }
3293
3294 extern cvar_t gl_picmip;
3295 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3296 {
3297         int j;
3298         unsigned char *pixels;
3299         unsigned char *bumppixels;
3300         unsigned char *basepixels = NULL;
3301         int basepixels_width = 0;
3302         int basepixels_height = 0;
3303         skinframe_t *skinframe;
3304         rtexture_t *ddsbase = NULL;
3305         qboolean ddshasalpha = false;
3306         float ddsavgcolor[4];
3307         char basename[MAX_QPATH];
3308         int miplevel = R_PicmipForFlags(textureflags);
3309         int savemiplevel = miplevel;
3310         int mymiplevel;
3311
3312         if (cls.state == ca_dedicated)
3313                 return NULL;
3314
3315         // return an existing skinframe if already loaded
3316         // if loading of the first image fails, don't make a new skinframe as it
3317         // would cause all future lookups of this to be missing
3318         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3319         if (skinframe && skinframe->base)
3320                 return skinframe;
3321
3322         Image_StripImageExtension(name, basename, sizeof(basename));
3323
3324         // check for DDS texture file first
3325         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3326         {
3327                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3328                 if (basepixels == NULL)
3329                         return NULL;
3330         }
3331
3332         // FIXME handle miplevel
3333
3334         if (developer_loading.integer)
3335                 Con_Printf("loading skin \"%s\"\n", name);
3336
3337         // we've got some pixels to store, so really allocate this new texture now
3338         if (!skinframe)
3339                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3340         textureflags &= ~TEXF_FORCE_RELOAD;
3341         skinframe->stain = NULL;
3342         skinframe->merged = NULL;
3343         skinframe->base = NULL;
3344         skinframe->pants = NULL;
3345         skinframe->shirt = NULL;
3346         skinframe->nmap = NULL;
3347         skinframe->gloss = NULL;
3348         skinframe->glow = NULL;
3349         skinframe->fog = NULL;
3350         skinframe->reflect = NULL;
3351         skinframe->hasalpha = false;
3352
3353         if (ddsbase)
3354         {
3355                 skinframe->base = ddsbase;
3356                 skinframe->hasalpha = ddshasalpha;
3357                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3358                 if (r_loadfog && skinframe->hasalpha)
3359                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3360                 //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]);
3361         }
3362         else
3363         {
3364                 basepixels_width = image_width;
3365                 basepixels_height = image_height;
3366                 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);
3367                 if (textureflags & TEXF_ALPHA)
3368                 {
3369                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3370                         {
3371                                 if (basepixels[j] < 255)
3372                                 {
3373                                         skinframe->hasalpha = true;
3374                                         break;
3375                                 }
3376                         }
3377                         if (r_loadfog && skinframe->hasalpha)
3378                         {
3379                                 // has transparent pixels
3380                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3381                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3382                                 {
3383                                         pixels[j+0] = 255;
3384                                         pixels[j+1] = 255;
3385                                         pixels[j+2] = 255;
3386                                         pixels[j+3] = basepixels[j+3];
3387                                 }
3388                                 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);
3389                                 Mem_Free(pixels);
3390                         }
3391                 }
3392                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3393 #ifndef USE_GLES2
3394                 //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]);
3395                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3396                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3397                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3398                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3399 #endif
3400         }
3401
3402         if (r_loaddds)
3403         {
3404                 mymiplevel = savemiplevel;
3405                 if (r_loadnormalmap)
3406                         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);
3407                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3408                 if (r_loadgloss)
3409                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3410                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3411                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3412                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3413         }
3414
3415         // _norm is the name used by tenebrae and has been adopted as standard
3416         if (r_loadnormalmap && skinframe->nmap == NULL)
3417         {
3418                 mymiplevel = savemiplevel;
3419                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3420                 {
3421                         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);
3422                         Mem_Free(pixels);
3423                         pixels = NULL;
3424                 }
3425                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3426                 {
3427                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3428                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3429                         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);
3430                         Mem_Free(pixels);
3431                         Mem_Free(bumppixels);
3432                 }
3433                 else if (r_shadow_bumpscale_basetexture.value > 0)
3434                 {
3435                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3436                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3437                         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);
3438                         Mem_Free(pixels);
3439                 }
3440 #ifndef USE_GLES2
3441                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3442                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3443 #endif
3444         }
3445
3446         // _luma is supported only for tenebrae compatibility
3447         // _glow is the preferred name
3448         mymiplevel = savemiplevel;
3449         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))))
3450         {
3451                 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);
3452 #ifndef USE_GLES2
3453                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3454                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3455 #endif
3456                 Mem_Free(pixels);pixels = NULL;
3457         }
3458
3459         mymiplevel = savemiplevel;
3460         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3461         {
3462                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3463 #ifndef USE_GLES2
3464                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3465                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3466 #endif
3467                 Mem_Free(pixels);
3468                 pixels = NULL;
3469         }
3470
3471         mymiplevel = savemiplevel;
3472         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3473         {
3474                 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);
3475 #ifndef USE_GLES2
3476                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3477                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3478 #endif
3479                 Mem_Free(pixels);
3480                 pixels = NULL;
3481         }
3482
3483         mymiplevel = savemiplevel;
3484         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3485         {
3486                 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);
3487 #ifndef USE_GLES2
3488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3489                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3490 #endif
3491                 Mem_Free(pixels);
3492                 pixels = NULL;
3493         }
3494
3495         mymiplevel = savemiplevel;
3496         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3497         {
3498                 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);
3499 #ifndef USE_GLES2
3500                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3501                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3502 #endif
3503                 Mem_Free(pixels);
3504                 pixels = NULL;
3505         }
3506
3507         if (basepixels)
3508                 Mem_Free(basepixels);
3509
3510         return skinframe;
3511 }
3512
3513 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3514 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3515 {
3516         int i;
3517         unsigned char *temp1, *temp2;
3518         skinframe_t *skinframe;
3519
3520         if (cls.state == ca_dedicated)
3521                 return NULL;
3522
3523         // if already loaded just return it, otherwise make a new skinframe
3524         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3525         if (skinframe && skinframe->base)
3526                 return skinframe;
3527         textureflags &= ~TEXF_FORCE_RELOAD;
3528
3529         skinframe->stain = NULL;
3530         skinframe->merged = NULL;
3531         skinframe->base = NULL;
3532         skinframe->pants = NULL;
3533         skinframe->shirt = NULL;
3534         skinframe->nmap = NULL;
3535         skinframe->gloss = NULL;
3536         skinframe->glow = NULL;
3537         skinframe->fog = NULL;
3538         skinframe->reflect = NULL;
3539         skinframe->hasalpha = false;
3540
3541         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3542         if (!skindata)
3543                 return NULL;
3544
3545         if (developer_loading.integer)
3546                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3547
3548         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3549         {
3550                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3551                 temp2 = temp1 + width * height * 4;
3552                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3553                 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);
3554                 Mem_Free(temp1);
3555         }
3556         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3557         if (textureflags & TEXF_ALPHA)
3558         {
3559                 for (i = 3;i < width * height * 4;i += 4)
3560                 {
3561                         if (skindata[i] < 255)
3562                         {
3563                                 skinframe->hasalpha = true;
3564                                 break;
3565                         }
3566                 }
3567                 if (r_loadfog && skinframe->hasalpha)
3568                 {
3569                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3570                         memcpy(fogpixels, skindata, width * height * 4);
3571                         for (i = 0;i < width * height * 4;i += 4)
3572                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3573                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3574                         Mem_Free(fogpixels);
3575                 }
3576         }
3577
3578         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3579         //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]);
3580
3581         return skinframe;
3582 }
3583
3584 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3585 {
3586         int i;
3587         int featuresmask;
3588         skinframe_t *skinframe;
3589
3590         if (cls.state == ca_dedicated)
3591                 return NULL;
3592
3593         // if already loaded just return it, otherwise make a new skinframe
3594         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3595         if (skinframe && skinframe->base)
3596                 return skinframe;
3597         textureflags &= ~TEXF_FORCE_RELOAD;
3598
3599         skinframe->stain = NULL;
3600         skinframe->merged = NULL;
3601         skinframe->base = NULL;
3602         skinframe->pants = NULL;
3603         skinframe->shirt = NULL;
3604         skinframe->nmap = NULL;
3605         skinframe->gloss = NULL;
3606         skinframe->glow = NULL;
3607         skinframe->fog = NULL;
3608         skinframe->reflect = NULL;
3609         skinframe->hasalpha = false;
3610
3611         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3612         if (!skindata)
3613                 return NULL;
3614
3615         if (developer_loading.integer)
3616                 Con_Printf("loading quake skin \"%s\"\n", name);
3617
3618         // 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)
3619         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3620         memcpy(skinframe->qpixels, skindata, width*height);
3621         skinframe->qwidth = width;
3622         skinframe->qheight = height;
3623
3624         featuresmask = 0;
3625         for (i = 0;i < width * height;i++)
3626                 featuresmask |= palette_featureflags[skindata[i]];
3627
3628         skinframe->hasalpha = false;
3629         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3630         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3631         skinframe->qgeneratemerged = true;
3632         skinframe->qgeneratebase = skinframe->qhascolormapping;
3633         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3634
3635         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3636         //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]);
3637
3638         return skinframe;
3639 }
3640
3641 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3642 {
3643         int width;
3644         int height;
3645         unsigned char *skindata;
3646
3647         if (!skinframe->qpixels)
3648                 return;
3649
3650         if (!skinframe->qhascolormapping)
3651                 colormapped = false;
3652
3653         if (colormapped)
3654         {
3655                 if (!skinframe->qgeneratebase)
3656                         return;
3657         }
3658         else
3659         {
3660                 if (!skinframe->qgeneratemerged)
3661                         return;
3662         }
3663
3664         width = skinframe->qwidth;
3665         height = skinframe->qheight;
3666         skindata = skinframe->qpixels;
3667
3668         if (skinframe->qgeneratenmap)
3669         {
3670                 unsigned char *temp1, *temp2;
3671                 skinframe->qgeneratenmap = false;
3672                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3673                 temp2 = temp1 + width * height * 4;
3674                 // use either a custom palette or the quake palette
3675                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3676                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3677                 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);
3678                 Mem_Free(temp1);
3679         }
3680
3681         if (skinframe->qgenerateglow)
3682         {
3683                 skinframe->qgenerateglow = false;
3684                 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
3685         }
3686
3687         if (colormapped)
3688         {
3689                 skinframe->qgeneratebase = false;
3690                 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);
3691                 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);
3692                 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);
3693         }
3694         else
3695         {
3696                 skinframe->qgeneratemerged = false;
3697                 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);
3698         }
3699
3700         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3701         {
3702                 Mem_Free(skinframe->qpixels);
3703                 skinframe->qpixels = NULL;
3704         }
3705 }
3706
3707 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)
3708 {
3709         int i;
3710         skinframe_t *skinframe;
3711
3712         if (cls.state == ca_dedicated)
3713                 return NULL;
3714
3715         // if already loaded just return it, otherwise make a new skinframe
3716         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3717         if (skinframe && skinframe->base)
3718                 return skinframe;
3719         textureflags &= ~TEXF_FORCE_RELOAD;
3720
3721         skinframe->stain = NULL;
3722         skinframe->merged = NULL;
3723         skinframe->base = NULL;
3724         skinframe->pants = NULL;
3725         skinframe->shirt = NULL;
3726         skinframe->nmap = NULL;
3727         skinframe->gloss = NULL;
3728         skinframe->glow = NULL;
3729         skinframe->fog = NULL;
3730         skinframe->reflect = NULL;
3731         skinframe->hasalpha = false;
3732
3733         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3734         if (!skindata)
3735                 return NULL;
3736
3737         if (developer_loading.integer)
3738                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3739
3740         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3741         if (textureflags & TEXF_ALPHA)
3742         {
3743                 for (i = 0;i < width * height;i++)
3744                 {
3745                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3746                         {
3747                                 skinframe->hasalpha = true;
3748                                 break;
3749                         }
3750                 }
3751                 if (r_loadfog && skinframe->hasalpha)
3752                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3753         }
3754
3755         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3756         //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]);
3757
3758         return skinframe;
3759 }
3760
3761 skinframe_t *R_SkinFrame_LoadMissing(void)
3762 {
3763         skinframe_t *skinframe;
3764
3765         if (cls.state == ca_dedicated)
3766                 return NULL;
3767
3768         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3769         skinframe->stain = NULL;
3770         skinframe->merged = NULL;
3771         skinframe->base = NULL;
3772         skinframe->pants = NULL;
3773         skinframe->shirt = NULL;
3774         skinframe->nmap = NULL;
3775         skinframe->gloss = NULL;
3776         skinframe->glow = NULL;
3777         skinframe->fog = NULL;
3778         skinframe->reflect = NULL;
3779         skinframe->hasalpha = false;
3780
3781         skinframe->avgcolor[0] = rand() / RAND_MAX;
3782         skinframe->avgcolor[1] = rand() / RAND_MAX;
3783         skinframe->avgcolor[2] = rand() / RAND_MAX;
3784         skinframe->avgcolor[3] = 1;
3785
3786         return skinframe;
3787 }
3788
3789 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3790 typedef struct suffixinfo_s
3791 {
3792         const char *suffix;
3793         qboolean flipx, flipy, flipdiagonal;
3794 }
3795 suffixinfo_t;
3796 static suffixinfo_t suffix[3][6] =
3797 {
3798         {
3799                 {"px",   false, false, false},
3800                 {"nx",   false, false, false},
3801                 {"py",   false, false, false},
3802                 {"ny",   false, false, false},
3803                 {"pz",   false, false, false},
3804                 {"nz",   false, false, false}
3805         },
3806         {
3807                 {"posx", false, false, false},
3808                 {"negx", false, false, false},
3809                 {"posy", false, false, false},
3810                 {"negy", false, false, false},
3811                 {"posz", false, false, false},
3812                 {"negz", false, false, false}
3813         },
3814         {
3815                 {"rt",    true, false,  true},
3816                 {"lf",   false,  true,  true},
3817                 {"ft",    true,  true, false},
3818                 {"bk",   false, false, false},
3819                 {"up",    true, false,  true},
3820                 {"dn",    true, false,  true}
3821         }
3822 };
3823
3824 static int componentorder[4] = {0, 1, 2, 3};
3825
3826 rtexture_t *R_LoadCubemap(const char *basename)
3827 {
3828         int i, j, cubemapsize;
3829         unsigned char *cubemappixels, *image_buffer;
3830         rtexture_t *cubemaptexture;
3831         char name[256];
3832         // must start 0 so the first loadimagepixels has no requested width/height
3833         cubemapsize = 0;
3834         cubemappixels = NULL;
3835         cubemaptexture = NULL;
3836         // keep trying different suffix groups (posx, px, rt) until one loads
3837         for (j = 0;j < 3 && !cubemappixels;j++)
3838         {
3839                 // load the 6 images in the suffix group
3840                 for (i = 0;i < 6;i++)
3841                 {
3842                         // generate an image name based on the base and and suffix
3843                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3844                         // load it
3845                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3846                         {
3847                                 // an image loaded, make sure width and height are equal
3848                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3849                                 {
3850                                         // if this is the first image to load successfully, allocate the cubemap memory
3851                                         if (!cubemappixels && image_width >= 1)
3852                                         {
3853                                                 cubemapsize = image_width;
3854                                                 // note this clears to black, so unavailable sides are black
3855                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3856                                         }
3857                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3858                                         if (cubemappixels)
3859                                                 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);
3860                                 }
3861                                 else
3862                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3863                                 // free the image
3864                                 Mem_Free(image_buffer);
3865                         }
3866                 }
3867         }
3868         // if a cubemap loaded, upload it
3869         if (cubemappixels)
3870         {
3871                 if (developer_loading.integer)
3872                         Con_Printf("loading cubemap \"%s\"\n", basename);
3873
3874                 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);
3875                 Mem_Free(cubemappixels);
3876         }
3877         else
3878         {
3879                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3880                 if (developer_loading.integer)
3881                 {
3882                         Con_Printf("(tried tried images ");
3883                         for (j = 0;j < 3;j++)
3884                                 for (i = 0;i < 6;i++)
3885                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3886                         Con_Print(" and was unable to find any of them).\n");
3887                 }
3888         }
3889         return cubemaptexture;
3890 }
3891
3892 rtexture_t *R_GetCubemap(const char *basename)
3893 {
3894         int i;
3895         for (i = 0;i < r_texture_numcubemaps;i++)
3896                 if (r_texture_cubemaps[i] != NULL)
3897                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3898                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3899         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3900                 return r_texture_whitecube;
3901         r_texture_numcubemaps++;
3902         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3903         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3904         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3905         return r_texture_cubemaps[i]->texture;
3906 }
3907
3908 void R_FreeCubemap(const char *basename)
3909 {
3910         int i;
3911
3912         for (i = 0;i < r_texture_numcubemaps;i++)
3913         {
3914                 if (r_texture_cubemaps[i] != NULL)
3915                 {
3916                         if (r_texture_cubemaps[i]->texture)
3917                         {
3918                                 if (developer_loading.integer)
3919                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3920                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3921                                 Mem_Free(r_texture_cubemaps[i]);
3922                                 r_texture_cubemaps[i] = NULL;
3923                         }
3924                 }
3925         }
3926 }
3927
3928 void R_FreeCubemaps(void)
3929 {
3930         int i;
3931         for (i = 0;i < r_texture_numcubemaps;i++)
3932         {
3933                 if (developer_loading.integer)
3934                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3935                 if (r_texture_cubemaps[i] != NULL)
3936                 {
3937                         if (r_texture_cubemaps[i]->texture)
3938                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3939                         Mem_Free(r_texture_cubemaps[i]);
3940                 }
3941         }
3942         r_texture_numcubemaps = 0;
3943 }
3944
3945 void R_Main_FreeViewCache(void)
3946 {
3947         if (r_refdef.viewcache.entityvisible)
3948                 Mem_Free(r_refdef.viewcache.entityvisible);
3949         if (r_refdef.viewcache.world_pvsbits)
3950                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3951         if (r_refdef.viewcache.world_leafvisible)
3952                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3953         if (r_refdef.viewcache.world_surfacevisible)
3954                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3955         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3956 }
3957
3958 void R_Main_ResizeViewCache(void)
3959 {
3960         int numentities = r_refdef.scene.numentities;
3961         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3962         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3963         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3964         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3965         if (r_refdef.viewcache.maxentities < numentities)
3966         {
3967                 r_refdef.viewcache.maxentities = numentities;
3968                 if (r_refdef.viewcache.entityvisible)
3969                         Mem_Free(r_refdef.viewcache.entityvisible);
3970                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3971         }
3972         if (r_refdef.viewcache.world_numclusters != numclusters)
3973         {
3974                 r_refdef.viewcache.world_numclusters = numclusters;
3975                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3976                 if (r_refdef.viewcache.world_pvsbits)
3977                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3978                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3979         }
3980         if (r_refdef.viewcache.world_numleafs != numleafs)
3981         {
3982                 r_refdef.viewcache.world_numleafs = numleafs;
3983                 if (r_refdef.viewcache.world_leafvisible)
3984                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3985                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3986         }
3987         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3988         {
3989                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3990                 if (r_refdef.viewcache.world_surfacevisible)
3991                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3992                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3993         }
3994 }
3995
3996 extern rtexture_t *loadingscreentexture;
3997 void gl_main_start(void)
3998 {
3999         loadingscreentexture = NULL;
4000         r_texture_blanknormalmap = NULL;
4001         r_texture_white = NULL;
4002         r_texture_grey128 = NULL;
4003         r_texture_black = NULL;
4004         r_texture_whitecube = NULL;
4005         r_texture_normalizationcube = NULL;
4006         r_texture_fogattenuation = NULL;
4007         r_texture_fogheighttexture = NULL;
4008         r_texture_gammaramps = NULL;
4009         r_texture_numcubemaps = 0;
4010
4011         r_loaddds = r_texture_dds_load.integer != 0;
4012         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4013
4014         switch(vid.renderpath)
4015         {
4016         case RENDERPATH_GL20:
4017         case RENDERPATH_D3D9:
4018         case RENDERPATH_D3D10:
4019         case RENDERPATH_D3D11:
4020         case RENDERPATH_SOFT:
4021         case RENDERPATH_GLES2:
4022                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4023                 Cvar_SetValueQuick(&gl_combine, 1);
4024                 Cvar_SetValueQuick(&r_glsl, 1);
4025                 r_loadnormalmap = true;
4026                 r_loadgloss = true;
4027                 r_loadfog = false;
4028                 break;
4029         case RENDERPATH_GL13:
4030         case RENDERPATH_GLES1:
4031                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4032                 Cvar_SetValueQuick(&gl_combine, 1);
4033                 Cvar_SetValueQuick(&r_glsl, 0);
4034                 r_loadnormalmap = false;
4035                 r_loadgloss = false;
4036                 r_loadfog = true;
4037                 break;
4038         case RENDERPATH_GL11:
4039                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4040                 Cvar_SetValueQuick(&gl_combine, 0);
4041                 Cvar_SetValueQuick(&r_glsl, 0);
4042                 r_loadnormalmap = false;
4043                 r_loadgloss = false;
4044                 r_loadfog = true;
4045                 break;
4046         }
4047
4048         R_AnimCache_Free();
4049         R_FrameData_Reset();
4050
4051         r_numqueries = 0;
4052         r_maxqueries = 0;
4053         memset(r_queries, 0, sizeof(r_queries));
4054
4055         r_qwskincache = NULL;
4056         r_qwskincache_size = 0;
4057
4058         // due to caching of texture_t references, the collision cache must be reset
4059         Collision_Cache_Reset(true);
4060
4061         // set up r_skinframe loading system for textures
4062         memset(&r_skinframe, 0, sizeof(r_skinframe));
4063         r_skinframe.loadsequence = 1;
4064         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4065
4066         r_main_texturepool = R_AllocTexturePool();
4067         R_BuildBlankTextures();
4068         R_BuildNoTexture();
4069         if (vid.support.arb_texture_cube_map)
4070         {
4071                 R_BuildWhiteCube();
4072                 R_BuildNormalizationCube();
4073         }
4074         r_texture_fogattenuation = NULL;
4075         r_texture_fogheighttexture = NULL;
4076         r_texture_gammaramps = NULL;
4077         //r_texture_fogintensity = NULL;
4078         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4079         memset(&r_waterstate, 0, sizeof(r_waterstate));
4080         r_glsl_permutation = NULL;
4081         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4082         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4083         glslshaderstring = NULL;
4084 #ifdef SUPPORTD3D
4085         r_hlsl_permutation = NULL;
4086         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4087         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4088 #endif
4089         hlslshaderstring = NULL;
4090         memset(&r_svbsp, 0, sizeof (r_svbsp));
4091
4092         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4093         r_texture_numcubemaps = 0;
4094
4095         r_refdef.fogmasktable_density = 0;
4096 }
4097
4098 void gl_main_shutdown(void)
4099 {
4100         R_AnimCache_Free();
4101         R_FrameData_Reset();
4102
4103         R_Main_FreeViewCache();
4104
4105         switch(vid.renderpath)
4106         {
4107         case RENDERPATH_GL11:
4108         case RENDERPATH_GL13:
4109         case RENDERPATH_GL20:
4110         case RENDERPATH_GLES1:
4111         case RENDERPATH_GLES2:
4112 #ifdef GL_SAMPLES_PASSED_ARB
4113                 if (r_maxqueries)
4114                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4115 #endif
4116                 break;
4117         case RENDERPATH_D3D9:
4118                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4119                 break;
4120         case RENDERPATH_D3D10:
4121                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4122                 break;
4123         case RENDERPATH_D3D11:
4124                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4125                 break;
4126         case RENDERPATH_SOFT:
4127                 break;
4128         }
4129
4130         r_numqueries = 0;
4131         r_maxqueries = 0;
4132         memset(r_queries, 0, sizeof(r_queries));
4133
4134         r_qwskincache = NULL;
4135         r_qwskincache_size = 0;
4136
4137         // clear out the r_skinframe state
4138         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4139         memset(&r_skinframe, 0, sizeof(r_skinframe));
4140
4141         if (r_svbsp.nodes)
4142                 Mem_Free(r_svbsp.nodes);
4143         memset(&r_svbsp, 0, sizeof (r_svbsp));
4144         R_FreeTexturePool(&r_main_texturepool);
4145         loadingscreentexture = NULL;
4146         r_texture_blanknormalmap = NULL;
4147         r_texture_white = NULL;
4148         r_texture_grey128 = NULL;
4149         r_texture_black = NULL;
4150         r_texture_whitecube = NULL;
4151         r_texture_normalizationcube = NULL;
4152         r_texture_fogattenuation = NULL;
4153         r_texture_fogheighttexture = NULL;
4154         r_texture_gammaramps = NULL;
4155         r_texture_numcubemaps = 0;
4156         //r_texture_fogintensity = NULL;
4157         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4158         memset(&r_waterstate, 0, sizeof(r_waterstate));
4159         R_GLSL_Restart_f();
4160
4161         r_glsl_permutation = NULL;
4162         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4163         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4164         glslshaderstring = NULL;
4165 #ifdef SUPPORTD3D
4166         r_hlsl_permutation = NULL;
4167         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4168         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4169 #endif
4170         hlslshaderstring = NULL;
4171 }
4172
4173 extern void CL_ParseEntityLump(char *entitystring);
4174 void gl_main_newmap(void)
4175 {
4176         // FIXME: move this code to client
4177         char *entities, entname[MAX_QPATH];
4178         if (r_qwskincache)
4179                 Mem_Free(r_qwskincache);
4180         r_qwskincache = NULL;
4181         r_qwskincache_size = 0;
4182         if (cl.worldmodel)
4183         {
4184                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4185                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4186                 {
4187                         CL_ParseEntityLump(entities);
4188                         Mem_Free(entities);
4189                         return;
4190                 }
4191                 if (cl.worldmodel->brush.entities)
4192                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4193         }
4194         R_Main_FreeViewCache();
4195
4196         R_FrameData_Reset();
4197 }
4198
4199 void GL_Main_Init(void)
4200 {
4201         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4202
4203         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4204         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4205         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4206         if (gamemode == GAME_NEHAHRA)
4207         {
4208                 Cvar_RegisterVariable (&gl_fogenable);
4209                 Cvar_RegisterVariable (&gl_fogdensity);
4210                 Cvar_RegisterVariable (&gl_fogred);
4211                 Cvar_RegisterVariable (&gl_foggreen);
4212                 Cvar_RegisterVariable (&gl_fogblue);
4213                 Cvar_RegisterVariable (&gl_fogstart);
4214                 Cvar_RegisterVariable (&gl_fogend);
4215                 Cvar_RegisterVariable (&gl_skyclip);
4216         }
4217         Cvar_RegisterVariable(&r_motionblur);
4218         Cvar_RegisterVariable(&r_damageblur);
4219         Cvar_RegisterVariable(&r_motionblur_averaging);
4220         Cvar_RegisterVariable(&r_motionblur_randomize);
4221         Cvar_RegisterVariable(&r_motionblur_minblur);
4222         Cvar_RegisterVariable(&r_motionblur_maxblur);
4223         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4224         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4225         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4226         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4227         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4228         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4229         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4230         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4231         Cvar_RegisterVariable(&r_equalize_entities_by);
4232         Cvar_RegisterVariable(&r_equalize_entities_to);
4233         Cvar_RegisterVariable(&r_depthfirst);
4234         Cvar_RegisterVariable(&r_useinfinitefarclip);
4235         Cvar_RegisterVariable(&r_farclip_base);
4236         Cvar_RegisterVariable(&r_farclip_world);
4237         Cvar_RegisterVariable(&r_nearclip);
4238         Cvar_RegisterVariable(&r_deformvertexes);
4239         Cvar_RegisterVariable(&r_transparent);
4240         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4241         Cvar_RegisterVariable(&r_showoverdraw);
4242         Cvar_RegisterVariable(&r_showbboxes);
4243         Cvar_RegisterVariable(&r_showsurfaces);
4244         Cvar_RegisterVariable(&r_showtris);
4245         Cvar_RegisterVariable(&r_shownormals);
4246         Cvar_RegisterVariable(&r_showlighting);
4247         Cvar_RegisterVariable(&r_showshadowvolumes);
4248         Cvar_RegisterVariable(&r_showcollisionbrushes);
4249         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4250         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4251         Cvar_RegisterVariable(&r_showdisabledepthtest);
4252         Cvar_RegisterVariable(&r_drawportals);
4253         Cvar_RegisterVariable(&r_drawentities);
4254         Cvar_RegisterVariable(&r_draw2d);
4255         Cvar_RegisterVariable(&r_drawworld);
4256         Cvar_RegisterVariable(&r_cullentities_trace);
4257         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4258         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4259         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4260         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4261         Cvar_RegisterVariable(&r_sortentities);
4262         Cvar_RegisterVariable(&r_drawviewmodel);
4263         Cvar_RegisterVariable(&r_drawexteriormodel);
4264         Cvar_RegisterVariable(&r_speeds);
4265         Cvar_RegisterVariable(&r_fullbrights);
4266         Cvar_RegisterVariable(&r_wateralpha);
4267         Cvar_RegisterVariable(&r_dynamic);
4268         Cvar_RegisterVariable(&r_fakelight);
4269         Cvar_RegisterVariable(&r_fakelight_intensity);
4270         Cvar_RegisterVariable(&r_fullbright);
4271         Cvar_RegisterVariable(&r_shadows);
4272         Cvar_RegisterVariable(&r_shadows_darken);
4273         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4274         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4275         Cvar_RegisterVariable(&r_shadows_throwdistance);
4276         Cvar_RegisterVariable(&r_shadows_throwdirection);
4277         Cvar_RegisterVariable(&r_shadows_focus);
4278         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4279         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4280         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4281         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4282         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4283         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4284         Cvar_RegisterVariable(&r_fog_exp2);
4285         Cvar_RegisterVariable(&r_fog_clear);
4286         Cvar_RegisterVariable(&r_drawfog);
4287         Cvar_RegisterVariable(&r_transparentdepthmasking);
4288         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4289         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4290         Cvar_RegisterVariable(&r_texture_dds_load);
4291         Cvar_RegisterVariable(&r_texture_dds_save);
4292         Cvar_RegisterVariable(&r_textureunits);
4293         Cvar_RegisterVariable(&gl_combine);
4294         Cvar_RegisterVariable(&r_viewfbo);
4295         Cvar_RegisterVariable(&r_viewscale);
4296         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4297         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4298         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4299         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4300         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4301         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4302         Cvar_RegisterVariable(&r_glsl);
4303         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4304         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4305         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4306         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4307         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4308         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4309         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4310         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4311         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4312         Cvar_RegisterVariable(&r_glsl_postprocess);
4313         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4314         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4315         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4316         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4317         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4318         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4319         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4320         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4321
4322         Cvar_RegisterVariable(&r_water);
4323         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4324         Cvar_RegisterVariable(&r_water_clippingplanebias);
4325         Cvar_RegisterVariable(&r_water_refractdistort);
4326         Cvar_RegisterVariable(&r_water_reflectdistort);
4327         Cvar_RegisterVariable(&r_water_scissormode);
4328         Cvar_RegisterVariable(&r_water_lowquality);
4329
4330         Cvar_RegisterVariable(&r_lerpsprites);
4331         Cvar_RegisterVariable(&r_lerpmodels);
4332         Cvar_RegisterVariable(&r_lerplightstyles);
4333         Cvar_RegisterVariable(&r_waterscroll);
4334         Cvar_RegisterVariable(&r_bloom);
4335         Cvar_RegisterVariable(&r_bloom_colorscale);
4336         Cvar_RegisterVariable(&r_bloom_brighten);
4337         Cvar_RegisterVariable(&r_bloom_blur);
4338         Cvar_RegisterVariable(&r_bloom_resolution);
4339         Cvar_RegisterVariable(&r_bloom_colorexponent);
4340         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4341         Cvar_RegisterVariable(&r_hdr);
4342         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4343         Cvar_RegisterVariable(&r_hdr_glowintensity);
4344         Cvar_RegisterVariable(&r_hdr_range);
4345         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4346         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4347         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4348         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4349         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4350         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4351         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4352         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4353         Cvar_RegisterVariable(&developer_texturelogging);
4354         Cvar_RegisterVariable(&gl_lightmaps);
4355         Cvar_RegisterVariable(&r_test);
4356         Cvar_RegisterVariable(&r_glsl_saturation);
4357         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4358         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4359         Cvar_RegisterVariable(&r_framedatasize);
4360         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4361                 Cvar_SetValue("r_fullbrights", 0);
4362         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4363 }
4364
4365 extern void R_Textures_Init(void);
4366 extern void GL_Draw_Init(void);
4367 extern void GL_Main_Init(void);
4368 extern void R_Shadow_Init(void);
4369 extern void R_Sky_Init(void);
4370 extern void GL_Surf_Init(void);
4371 extern void R_Particles_Init(void);
4372 extern void R_Explosion_Init(void);
4373 extern void gl_backend_init(void);
4374 extern void Sbar_Init(void);
4375 extern void R_LightningBeams_Init(void);
4376 extern void Mod_RenderInit(void);
4377 extern void Font_Init(void);
4378
4379 void Render_Init(void)
4380 {
4381         gl_backend_init();
4382         R_Textures_Init();
4383         GL_Main_Init();
4384         Font_Init();
4385         GL_Draw_Init();
4386         R_Shadow_Init();
4387         R_Sky_Init();
4388         GL_Surf_Init();
4389         Sbar_Init();
4390         R_Particles_Init();
4391         R_Explosion_Init();
4392         R_LightningBeams_Init();
4393         Mod_RenderInit();
4394 }
4395
4396 /*
4397 ===============
4398 GL_Init
4399 ===============
4400 */
4401 #ifndef USE_GLES2
4402 extern char *ENGINE_EXTENSIONS;
4403 void GL_Init (void)
4404 {
4405         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4406         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4407         gl_version = (const char *)qglGetString(GL_VERSION);
4408         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4409
4410         if (!gl_extensions)
4411                 gl_extensions = "";
4412         if (!gl_platformextensions)
4413                 gl_platformextensions = "";
4414
4415         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4416         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4417         Con_Printf("GL_VERSION: %s\n", gl_version);
4418         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4419         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4420
4421         VID_CheckExtensions();
4422
4423         // LordHavoc: report supported extensions
4424         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4425
4426         // clear to black (loading plaque will be seen over this)
4427         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4428 }
4429 #endif
4430
4431 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4432 {
4433         int i;
4434         mplane_t *p;
4435         if (r_trippy.integer)
4436                 return false;
4437         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4438         {
4439                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4440                 if (i == 4)
4441                         continue;
4442                 p = r_refdef.view.frustum + i;
4443                 switch(p->signbits)
4444                 {
4445                 default:
4446                 case 0:
4447                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4448                                 return true;
4449                         break;
4450                 case 1:
4451                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4452                                 return true;
4453                         break;
4454                 case 2:
4455                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4456                                 return true;
4457                         break;
4458                 case 3:
4459                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4460                                 return true;
4461                         break;
4462                 case 4:
4463                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4464                                 return true;
4465                         break;
4466                 case 5:
4467                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4468                                 return true;
4469                         break;
4470                 case 6:
4471                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4472                                 return true;
4473                         break;
4474                 case 7:
4475                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 }
4479         }
4480         return false;
4481 }
4482
4483 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4484 {
4485         int i;
4486         const mplane_t *p;
4487         if (r_trippy.integer)
4488                 return false;
4489         for (i = 0;i < numplanes;i++)
4490         {
4491                 p = planes + i;
4492                 switch(p->signbits)
4493                 {
4494                 default:
4495                 case 0:
4496                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4497                                 return true;
4498                         break;
4499                 case 1:
4500                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 2:
4504                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 case 3:
4508                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4509                                 return true;
4510                         break;
4511                 case 4:
4512                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4513                                 return true;
4514                         break;
4515                 case 5:
4516                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4517                                 return true;
4518                         break;
4519                 case 6:
4520                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4521                                 return true;
4522                         break;
4523                 case 7:
4524                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4525                                 return true;
4526                         break;
4527                 }
4528         }
4529         return false;
4530 }
4531
4532 //==================================================================================
4533
4534 // LordHavoc: this stores temporary data used within the same frame
4535
4536 typedef struct r_framedata_mem_s
4537 {
4538         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4539         size_t size; // how much usable space
4540         size_t current; // how much space in use
4541         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4542         size_t wantedsize; // how much space was allocated
4543         unsigned char *data; // start of real data (16byte aligned)
4544 }
4545 r_framedata_mem_t;
4546
4547 static r_framedata_mem_t *r_framedata_mem;
4548
4549 void R_FrameData_Reset(void)
4550 {
4551         while (r_framedata_mem)
4552         {
4553                 r_framedata_mem_t *next = r_framedata_mem->purge;
4554                 Mem_Free(r_framedata_mem);
4555                 r_framedata_mem = next;
4556         }
4557 }
4558
4559 void R_FrameData_Resize(void)
4560 {
4561         size_t wantedsize;
4562         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4563         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4564         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4565         {
4566                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4567                 newmem->wantedsize = wantedsize;
4568                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4569                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4570                 newmem->current = 0;
4571                 newmem->mark = 0;
4572                 newmem->purge = r_framedata_mem;
4573                 r_framedata_mem = newmem;
4574         }
4575 }
4576
4577 void R_FrameData_NewFrame(void)
4578 {
4579         R_FrameData_Resize();
4580         if (!r_framedata_mem)
4581                 return;
4582         // if we ran out of space on the last frame, free the old memory now
4583         while (r_framedata_mem->purge)
4584         {
4585                 // repeatedly remove the second item in the list, leaving only head
4586                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4587                 Mem_Free(r_framedata_mem->purge);
4588                 r_framedata_mem->purge = next;
4589         }
4590         // reset the current mem pointer
4591         r_framedata_mem->current = 0;
4592         r_framedata_mem->mark = 0;
4593 }
4594
4595 void *R_FrameData_Alloc(size_t size)
4596 {
4597         void *data;
4598
4599         // align to 16 byte boundary - the data pointer is already aligned, so we
4600         // only need to ensure the size of every allocation is also aligned
4601         size = (size + 15) & ~15;
4602
4603         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4604         {
4605                 // emergency - we ran out of space, allocate more memory
4606                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4607                 R_FrameData_Resize();
4608         }
4609
4610         data = r_framedata_mem->data + r_framedata_mem->current;
4611         r_framedata_mem->current += size;
4612
4613         // count the usage for stats
4614         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4615         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4616
4617         return (void *)data;
4618 }
4619
4620 void *R_FrameData_Store(size_t size, void *data)
4621 {
4622         void *d = R_FrameData_Alloc(size);
4623         if (d && data)
4624                 memcpy(d, data, size);
4625         return d;
4626 }
4627
4628 void R_FrameData_SetMark(void)
4629 {
4630         if (!r_framedata_mem)
4631                 return;
4632         r_framedata_mem->mark = r_framedata_mem->current;
4633 }
4634
4635 void R_FrameData_ReturnToMark(void)
4636 {
4637         if (!r_framedata_mem)
4638                 return;
4639         r_framedata_mem->current = r_framedata_mem->mark;
4640 }
4641
4642 //==================================================================================
4643
4644 // LordHavoc: animcache originally written by Echon, rewritten since then
4645
4646 /**
4647  * Animation cache prevents re-generating mesh data for an animated model
4648  * multiple times in one frame for lighting, shadowing, reflections, etc.
4649  */
4650
4651 void R_AnimCache_Free(void)
4652 {
4653 }
4654
4655 void R_AnimCache_ClearCache(void)
4656 {
4657         int i;
4658         entity_render_t *ent;
4659
4660         for (i = 0;i < r_refdef.scene.numentities;i++)
4661         {
4662                 ent = r_refdef.scene.entities[i];
4663                 ent->animcache_vertex3f = NULL;
4664                 ent->animcache_normal3f = NULL;
4665                 ent->animcache_svector3f = NULL;
4666                 ent->animcache_tvector3f = NULL;
4667                 ent->animcache_vertexmesh = NULL;
4668                 ent->animcache_vertex3fbuffer = NULL;
4669                 ent->animcache_vertexmeshbuffer = NULL;
4670         }
4671 }
4672
4673 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4674 {
4675         int i;
4676
4677         // check if we need the meshbuffers
4678         if (!vid.useinterleavedarrays)
4679                 return;
4680
4681         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4682                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4683         // TODO: upload vertex3f buffer?
4684         if (ent->animcache_vertexmesh)
4685         {
4686                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4687                 for (i = 0;i < numvertices;i++)
4688                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4689                 if (ent->animcache_svector3f)
4690                         for (i = 0;i < numvertices;i++)
4691                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4692                 if (ent->animcache_tvector3f)
4693                         for (i = 0;i < numvertices;i++)
4694                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4695                 if (ent->animcache_normal3f)
4696                         for (i = 0;i < numvertices;i++)
4697                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4698                 // TODO: upload vertexmeshbuffer?
4699         }
4700 }
4701
4702 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4703 {
4704         dp_model_t *model = ent->model;
4705         int numvertices;
4706         // see if it's already cached this frame
4707         if (ent->animcache_vertex3f)
4708         {
4709                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4710                 if (wantnormals || wanttangents)
4711                 {
4712                         if (ent->animcache_normal3f)
4713                                 wantnormals = false;
4714                         if (ent->animcache_svector3f)
4715                                 wanttangents = false;
4716                         if (wantnormals || wanttangents)
4717                         {
4718                                 numvertices = model->surfmesh.num_vertices;
4719                                 if (wantnormals)
4720                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4721                                 if (wanttangents)
4722                                 {
4723                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4724                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4725                                 }
4726                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4727                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4728                         }
4729                 }
4730         }
4731         else
4732         {
4733                 // see if this ent is worth caching
4734                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4735                         return false;
4736                 // get some memory for this entity and generate mesh data
4737                 numvertices = model->surfmesh.num_vertices;
4738                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4739                 if (wantnormals)
4740                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4741                 if (wanttangents)
4742                 {
4743                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4744                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4745                 }
4746                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4747                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4748         }
4749         return true;
4750 }
4751
4752 void R_AnimCache_CacheVisibleEntities(void)
4753 {
4754         int i;
4755         qboolean wantnormals = true;
4756         qboolean wanttangents = !r_showsurfaces.integer;
4757
4758         switch(vid.renderpath)
4759         {
4760         case RENDERPATH_GL20:
4761         case RENDERPATH_D3D9:
4762         case RENDERPATH_D3D10:
4763         case RENDERPATH_D3D11:
4764         case RENDERPATH_GLES2:
4765                 break;
4766         case RENDERPATH_GL11:
4767         case RENDERPATH_GL13:
4768         case RENDERPATH_GLES1:
4769                 wanttangents = false;
4770                 break;
4771         case RENDERPATH_SOFT:
4772                 break;
4773         }
4774
4775         if (r_shownormals.integer)
4776                 wanttangents = wantnormals = true;
4777
4778         // TODO: thread this
4779         // NOTE: R_PrepareRTLights() also caches entities
4780
4781         for (i = 0;i < r_refdef.scene.numentities;i++)
4782                 if (r_refdef.viewcache.entityvisible[i])
4783                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4784 }
4785
4786 //==================================================================================
4787
4788 extern cvar_t r_overheadsprites_pushback;
4789
4790 static void R_View_UpdateEntityLighting (void)
4791 {
4792         int i;
4793         entity_render_t *ent;
4794         vec3_t tempdiffusenormal, avg;
4795         vec_t f, fa, fd, fdd;
4796         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4797
4798         for (i = 0;i < r_refdef.scene.numentities;i++)
4799         {
4800                 ent = r_refdef.scene.entities[i];
4801
4802                 // skip unseen models
4803                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4804                         continue;
4805
4806                 // skip bsp models
4807                 if (ent->model && ent->model->brush.num_leafs)
4808                 {
4809                         // TODO: use modellight for r_ambient settings on world?
4810                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4811                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4812                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4813                         continue;
4814                 }
4815
4816                 // fetch the lighting from the worldmodel data
4817                 VectorClear(ent->modellight_ambient);
4818                 VectorClear(ent->modellight_diffuse);
4819                 VectorClear(tempdiffusenormal);
4820                 if (ent->flags & RENDER_LIGHT)
4821                 {
4822                         vec3_t org;
4823                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4824
4825                         // complete lightning for lit sprites
4826                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4827                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4828                         {
4829                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4830                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4831                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4832                         }
4833                         else
4834                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4835
4836                         if(ent->flags & RENDER_EQUALIZE)
4837                         {
4838                                 // first fix up ambient lighting...
4839                                 if(r_equalize_entities_minambient.value > 0)
4840                                 {
4841                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4842                                         if(fd > 0)
4843                                         {
4844                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4845                                                 if(fa < r_equalize_entities_minambient.value * fd)
4846                                                 {
4847                                                         // solve:
4848                                                         //   fa'/fd' = minambient
4849                                                         //   fa'+0.25*fd' = fa+0.25*fd
4850                                                         //   ...
4851                                                         //   fa' = fd' * minambient
4852                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4853                                                         //   ...
4854                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4855                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4856                                                         //   ...
4857                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4858                                                         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
4859                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4860                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4861                                                 }
4862                                         }
4863                                 }
4864
4865                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4866                                 {
4867                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4868                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4869                                         f = fa + 0.25 * fd;
4870                                         if(f > 0)
4871                                         {
4872                                                 // adjust brightness and saturation to target
4873                                                 avg[0] = avg[1] = avg[2] = fa / f;
4874                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4875                                                 avg[0] = avg[1] = avg[2] = fd / f;
4876                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4877                                         }
4878                                 }
4879                         }
4880                 }
4881                 else // highly rare
4882                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4883
4884                 // move the light direction into modelspace coordinates for lighting code
4885                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4886                 if(VectorLength2(ent->modellight_lightdir) == 0)
4887                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4888                 VectorNormalize(ent->modellight_lightdir);
4889         }
4890 }
4891
4892 #define MAX_LINEOFSIGHTTRACES 64
4893
4894 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4895 {
4896         int i;
4897         vec3_t boxmins, boxmaxs;
4898         vec3_t start;
4899         vec3_t end;
4900         dp_model_t *model = r_refdef.scene.worldmodel;
4901
4902         if (!model || !model->brush.TraceLineOfSight)
4903                 return true;
4904
4905         // expand the box a little
4906         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4907         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4908         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4909         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4910         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4911         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4912
4913         // return true if eye is inside enlarged box
4914         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4915                 return true;
4916
4917         // try center
4918         VectorCopy(eye, start);
4919         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4920         if (model->brush.TraceLineOfSight(model, start, end))
4921                 return true;
4922
4923         // try various random positions
4924         for (i = 0;i < numsamples;i++)
4925         {
4926                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4927                 if (model->brush.TraceLineOfSight(model, start, end))
4928                         return true;
4929         }
4930
4931         return false;
4932 }
4933
4934
4935 static void R_View_UpdateEntityVisible (void)
4936 {
4937         int i;
4938         int renderimask;
4939         int samples;
4940         entity_render_t *ent;
4941
4942         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4943                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4944                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4945                 :                                                          RENDER_EXTERIORMODEL;
4946         if (!r_drawviewmodel.integer)
4947                 renderimask |= RENDER_VIEWMODEL;
4948         if (!r_drawexteriormodel.integer)
4949                 renderimask |= RENDER_EXTERIORMODEL;
4950         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4951         {
4952                 // worldmodel can check visibility
4953                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4954                 for (i = 0;i < r_refdef.scene.numentities;i++)
4955                 {
4956                         ent = r_refdef.scene.entities[i];
4957                         if (!(ent->flags & renderimask))
4958                         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)))
4959                         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))
4960                                 r_refdef.viewcache.entityvisible[i] = true;
4961                 }
4962         }
4963         else
4964         {
4965                 // no worldmodel or it can't check visibility
4966                 for (i = 0;i < r_refdef.scene.numentities;i++)
4967                 {
4968                         ent = r_refdef.scene.entities[i];
4969                         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));
4970                 }
4971         }
4972         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4973                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4974         {
4975                 for (i = 0;i < r_refdef.scene.numentities;i++)
4976                 {
4977                         if (!r_refdef.viewcache.entityvisible[i])
4978                                 continue;
4979                         ent = r_refdef.scene.entities[i];
4980                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4981                         {
4982                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4983                                 if (samples < 0)
4984                                         continue; // temp entities do pvs only
4985                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4986                                         ent->last_trace_visibility = realtime;
4987                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4988                                         r_refdef.viewcache.entityvisible[i] = 0;
4989                         }
4990                 }
4991         }
4992 }
4993
4994 /// only used if skyrendermasked, and normally returns false
4995 int R_DrawBrushModelsSky (void)
4996 {
4997         int i, sky;
4998         entity_render_t *ent;
4999
5000         sky = false;
5001         for (i = 0;i < r_refdef.scene.numentities;i++)
5002         {
5003                 if (!r_refdef.viewcache.entityvisible[i])
5004                         continue;
5005                 ent = r_refdef.scene.entities[i];
5006                 if (!ent->model || !ent->model->DrawSky)
5007                         continue;
5008                 ent->model->DrawSky(ent);
5009                 sky = true;
5010         }
5011         return sky;
5012 }
5013
5014 static void R_DrawNoModel(entity_render_t *ent);
5015 static void R_DrawModels(void)
5016 {
5017         int i;
5018         entity_render_t *ent;
5019
5020         for (i = 0;i < r_refdef.scene.numentities;i++)
5021         {
5022                 if (!r_refdef.viewcache.entityvisible[i])
5023                         continue;
5024                 ent = r_refdef.scene.entities[i];
5025                 r_refdef.stats.entities++;
5026                 /*
5027                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5028                 {
5029                         vec3_t f, l, u, o;
5030                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5031                         Con_Printf("R_DrawModels\n");
5032                         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]);
5033                         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);
5034                         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);
5035                 }
5036                 */
5037                 if (ent->model && ent->model->Draw != NULL)
5038                         ent->model->Draw(ent);
5039                 else
5040                         R_DrawNoModel(ent);
5041         }
5042 }
5043
5044 static void R_DrawModelsDepth(void)
5045 {
5046         int i;
5047         entity_render_t *ent;
5048
5049         for (i = 0;i < r_refdef.scene.numentities;i++)
5050         {
5051                 if (!r_refdef.viewcache.entityvisible[i])
5052                         continue;
5053                 ent = r_refdef.scene.entities[i];
5054                 if (ent->model && ent->model->DrawDepth != NULL)
5055                         ent->model->DrawDepth(ent);
5056         }
5057 }
5058
5059 static void R_DrawModelsDebug(void)
5060 {
5061         int i;
5062         entity_render_t *ent;
5063
5064         for (i = 0;i < r_refdef.scene.numentities;i++)
5065         {
5066                 if (!r_refdef.viewcache.entityvisible[i])
5067                         continue;
5068                 ent = r_refdef.scene.entities[i];
5069                 if (ent->model && ent->model->DrawDebug != NULL)
5070                         ent->model->DrawDebug(ent);
5071         }
5072 }
5073
5074 static void R_DrawModelsAddWaterPlanes(void)
5075 {
5076         int i;
5077         entity_render_t *ent;
5078
5079         for (i = 0;i < r_refdef.scene.numentities;i++)
5080         {
5081                 if (!r_refdef.viewcache.entityvisible[i])
5082                         continue;
5083                 ent = r_refdef.scene.entities[i];
5084                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5085                         ent->model->DrawAddWaterPlanes(ent);
5086         }
5087 }
5088
5089 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5090 {
5091         if (r_hdr_irisadaptation.integer)
5092         {
5093                 vec3_t ambient;
5094                 vec3_t diffuse;
5095                 vec3_t diffusenormal;
5096                 vec_t brightness;
5097                 vec_t goal;
5098                 vec_t current;
5099                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5100                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5101                 brightness = max(0.0000001f, brightness);
5102                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5103                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5104                 current = r_hdr_irisadaptation_value.value;
5105                 if (current < goal)
5106                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5107                 else if (current > goal)
5108                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5109                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5110                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5111         }
5112         else if (r_hdr_irisadaptation_value.value != 1.0f)
5113                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5114 }
5115
5116 static void R_View_SetFrustum(const int *scissor)
5117 {
5118         int i;
5119         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5120         vec3_t forward, left, up, origin, v;
5121
5122         if(scissor)
5123         {
5124                 // flipped x coordinates (because x points left here)
5125                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5126                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5127
5128                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5129                 switch(vid.renderpath)
5130                 {
5131                         case RENDERPATH_D3D9:
5132                         case RENDERPATH_D3D10:
5133                         case RENDERPATH_D3D11:
5134                                 // non-flipped y coordinates
5135                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5136                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5137                                 break;
5138                         case RENDERPATH_SOFT:
5139                         case RENDERPATH_GL11:
5140                         case RENDERPATH_GL13:
5141                         case RENDERPATH_GL20:
5142                         case RENDERPATH_GLES1:
5143                         case RENDERPATH_GLES2:
5144                                 // non-flipped y coordinates
5145                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5146                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5147                                 break;
5148                 }
5149         }
5150
5151         // we can't trust r_refdef.view.forward and friends in reflected scenes
5152         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5153
5154 #if 0
5155         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5156         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5157         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5158         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5159         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5160         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5161         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5162         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5163         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5164         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5165         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5166         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5167 #endif
5168
5169 #if 0
5170         zNear = r_refdef.nearclip;
5171         nudge = 1.0 - 1.0 / (1<<23);
5172         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5173         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5174         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5175         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5176         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5177         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5178         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5179         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5180 #endif
5181
5182
5183
5184 #if 0
5185         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5186         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5187         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5188         r_refdef.view.frustum[0].dist = m[15] - m[12];
5189
5190         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5191         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5192         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5193         r_refdef.view.frustum[1].dist = m[15] + m[12];
5194
5195         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5196         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5197         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5198         r_refdef.view.frustum[2].dist = m[15] - m[13];
5199
5200         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5201         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5202         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5203         r_refdef.view.frustum[3].dist = m[15] + m[13];
5204
5205         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5206         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5207         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5208         r_refdef.view.frustum[4].dist = m[15] - m[14];
5209
5210         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5211         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5212         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5213         r_refdef.view.frustum[5].dist = m[15] + m[14];
5214 #endif
5215
5216         if (r_refdef.view.useperspective)
5217         {
5218                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5219                 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]);
5220                 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]);
5221                 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]);
5222                 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]);
5223
5224                 // then the normals from the corners relative to origin
5225                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5226                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5227                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5228                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5229
5230                 // in a NORMAL view, forward cross left == up
5231                 // in a REFLECTED view, forward cross left == down
5232                 // so our cross products above need to be adjusted for a left handed coordinate system
5233                 CrossProduct(forward, left, v);
5234                 if(DotProduct(v, up) < 0)
5235                 {
5236                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5237                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5238                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5239                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5240                 }
5241
5242                 // Leaving those out was a mistake, those were in the old code, and they
5243                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5244                 // I couldn't reproduce it after adding those normalizations. --blub
5245                 VectorNormalize(r_refdef.view.frustum[0].normal);
5246                 VectorNormalize(r_refdef.view.frustum[1].normal);
5247                 VectorNormalize(r_refdef.view.frustum[2].normal);
5248                 VectorNormalize(r_refdef.view.frustum[3].normal);
5249
5250                 // make the corners absolute
5251                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5252                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5253                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5254                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5255
5256                 // one more normal
5257                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5258
5259                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5260                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5261                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5262                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5263                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5264         }
5265         else
5266         {
5267                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5268                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5269                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5270                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5271                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5272                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5273                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5274                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5275                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5276                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5277         }
5278         r_refdef.view.numfrustumplanes = 5;
5279
5280         if (r_refdef.view.useclipplane)
5281         {
5282                 r_refdef.view.numfrustumplanes = 6;
5283                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5284         }
5285
5286         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5287                 PlaneClassify(r_refdef.view.frustum + i);
5288
5289         // LordHavoc: note to all quake engine coders, Quake had a special case
5290         // for 90 degrees which assumed a square view (wrong), so I removed it,
5291         // Quake2 has it disabled as well.
5292
5293         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5294         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5295         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5296         //PlaneClassify(&frustum[0]);
5297
5298         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5299         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5300         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5301         //PlaneClassify(&frustum[1]);
5302
5303         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5304         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5305         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5306         //PlaneClassify(&frustum[2]);
5307
5308         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5309         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5310         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5311         //PlaneClassify(&frustum[3]);
5312
5313         // nearclip plane
5314         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5315         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5316         //PlaneClassify(&frustum[4]);
5317 }
5318
5319 void R_View_UpdateWithScissor(const int *myscissor)
5320 {
5321         R_Main_ResizeViewCache();
5322         R_View_SetFrustum(myscissor);
5323         R_View_WorldVisibility(r_refdef.view.useclipplane);
5324         R_View_UpdateEntityVisible();
5325         R_View_UpdateEntityLighting();
5326 }
5327
5328 void R_View_Update(void)
5329 {
5330         R_Main_ResizeViewCache();
5331         R_View_SetFrustum(NULL);
5332         R_View_WorldVisibility(r_refdef.view.useclipplane);
5333         R_View_UpdateEntityVisible();
5334         R_View_UpdateEntityLighting();
5335 }
5336
5337 float viewscalefpsadjusted = 1.0f;
5338
5339 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5340 {
5341         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5342         scale = bound(0.03125f, scale, 1.0f);
5343         *outwidth = (int)ceil(width * scale);
5344         *outheight = (int)ceil(height * scale);
5345 }
5346
5347 void R_Mesh_SetMainRenderTargets(void)
5348 {
5349         if (r_bloomstate.fbo_framebuffer)
5350                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5351         else
5352                 R_Mesh_ResetRenderTargets();
5353 }
5354
5355 void R_SetupView(qboolean allowwaterclippingplane)
5356 {
5357         const float *customclipplane = NULL;
5358         float plane[4];
5359         int scaledwidth, scaledheight;
5360         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5361         {
5362                 // LordHavoc: couldn't figure out how to make this approach the
5363                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5364                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5365                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5366                         dist = r_refdef.view.clipplane.dist;
5367                 plane[0] = r_refdef.view.clipplane.normal[0];
5368                 plane[1] = r_refdef.view.clipplane.normal[1];
5369                 plane[2] = r_refdef.view.clipplane.normal[2];
5370                 plane[3] = -dist;
5371                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5372         }
5373
5374         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5375         if (!r_refdef.view.useperspective)
5376                 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);
5377         else if (vid.stencil && r_useinfinitefarclip.integer)
5378                 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);
5379         else
5380                 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);
5381         R_Mesh_SetMainRenderTargets();
5382         R_SetViewport(&r_refdef.view.viewport);
5383         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5384         {
5385                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5386                 float screenplane[4];
5387                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5388                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5389                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5390                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5391                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5392         }
5393 }
5394
5395 void R_EntityMatrix(const matrix4x4_t *matrix)
5396 {
5397         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5398         {
5399                 gl_modelmatrixchanged = false;
5400                 gl_modelmatrix = *matrix;
5401                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5402                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5403                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5404                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5405                 CHECKGLERROR
5406                 switch(vid.renderpath)
5407                 {
5408                 case RENDERPATH_D3D9:
5409 #ifdef SUPPORTD3D
5410                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5411                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5412 #endif
5413                         break;
5414                 case RENDERPATH_D3D10:
5415                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5416                         break;
5417                 case RENDERPATH_D3D11:
5418                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5419                         break;
5420                 case RENDERPATH_GL11:
5421                 case RENDERPATH_GL13:
5422                 case RENDERPATH_GLES1:
5423                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5424                         break;
5425                 case RENDERPATH_SOFT:
5426                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5427                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5428                         break;
5429                 case RENDERPATH_GL20:
5430                 case RENDERPATH_GLES2:
5431                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5432                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5433                         break;
5434                 }
5435         }
5436 }
5437
5438 void R_ResetViewRendering2D(void)
5439 {
5440         r_viewport_t viewport;
5441         DrawQ_Finish();
5442
5443         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5444         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);
5445         R_Mesh_ResetRenderTargets();
5446         R_SetViewport(&viewport);
5447         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5448         GL_Color(1, 1, 1, 1);
5449         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5450         GL_BlendFunc(GL_ONE, GL_ZERO);
5451         GL_ScissorTest(false);
5452         GL_DepthMask(false);
5453         GL_DepthRange(0, 1);
5454         GL_DepthTest(false);
5455         GL_DepthFunc(GL_LEQUAL);
5456         R_EntityMatrix(&identitymatrix);
5457         R_Mesh_ResetTextureState();
5458         GL_PolygonOffset(0, 0);
5459         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5460         switch(vid.renderpath)
5461         {
5462         case RENDERPATH_GL11:
5463         case RENDERPATH_GL13:
5464         case RENDERPATH_GL20:
5465         case RENDERPATH_GLES1:
5466         case RENDERPATH_GLES2:
5467                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5468                 break;
5469         case RENDERPATH_D3D9:
5470         case RENDERPATH_D3D10:
5471         case RENDERPATH_D3D11:
5472         case RENDERPATH_SOFT:
5473                 break;
5474         }
5475         GL_CullFace(GL_NONE);
5476 }
5477
5478 void R_ResetViewRendering3D(void)
5479 {
5480         DrawQ_Finish();
5481
5482         R_SetupView(true);
5483         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5484         GL_Color(1, 1, 1, 1);
5485         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5486         GL_BlendFunc(GL_ONE, GL_ZERO);
5487         GL_ScissorTest(true);
5488         GL_DepthMask(true);
5489         GL_DepthRange(0, 1);
5490         GL_DepthTest(true);
5491         GL_DepthFunc(GL_LEQUAL);
5492         R_EntityMatrix(&identitymatrix);
5493         R_Mesh_ResetTextureState();
5494         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5495         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5496         switch(vid.renderpath)
5497         {
5498         case RENDERPATH_GL11:
5499         case RENDERPATH_GL13:
5500         case RENDERPATH_GL20:
5501         case RENDERPATH_GLES1:
5502         case RENDERPATH_GLES2:
5503                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5504                 break;
5505         case RENDERPATH_D3D9:
5506         case RENDERPATH_D3D10:
5507         case RENDERPATH_D3D11:
5508         case RENDERPATH_SOFT:
5509                 break;
5510         }
5511         GL_CullFace(r_refdef.view.cullface_back);
5512 }
5513
5514 /*
5515 ================
5516 R_RenderView_UpdateViewVectors
5517 ================
5518 */
5519 static void R_RenderView_UpdateViewVectors(void)
5520 {
5521         // break apart the view matrix into vectors for various purposes
5522         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5523         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5524         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5525         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5526         // make an inverted copy of the view matrix for tracking sprites
5527         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5528 }
5529
5530 void R_RenderScene(void);
5531 void R_RenderWaterPlanes(void);
5532
5533 static void R_Water_StartFrame(void)
5534 {
5535         int i;
5536         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5537         r_waterstate_waterplane_t *p;
5538
5539         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5540                 return;
5541
5542         switch(vid.renderpath)
5543         {
5544         case RENDERPATH_GL20:
5545         case RENDERPATH_D3D9:
5546         case RENDERPATH_D3D10:
5547         case RENDERPATH_D3D11:
5548         case RENDERPATH_SOFT:
5549         case RENDERPATH_GLES2:
5550                 break;
5551         case RENDERPATH_GL11:
5552         case RENDERPATH_GL13:
5553         case RENDERPATH_GLES1:
5554                 return;
5555         }
5556
5557         // set waterwidth and waterheight to the water resolution that will be
5558         // used (often less than the screen resolution for faster rendering)
5559         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5560
5561         // calculate desired texture sizes
5562         // can't use water if the card does not support the texture size
5563         if (!r_water.integer || r_showsurfaces.integer)
5564                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5565         else if (vid.support.arb_texture_non_power_of_two)
5566         {
5567                 texturewidth = waterwidth;
5568                 textureheight = waterheight;
5569                 camerawidth = waterwidth;
5570                 cameraheight = waterheight;
5571         }
5572         else
5573         {
5574                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5575                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5576                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5577                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5578         }
5579
5580         // allocate textures as needed
5581         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5582         {
5583                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5584                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5585                 {
5586                         if (p->texture_refraction)
5587                                 R_FreeTexture(p->texture_refraction);
5588                         p->texture_refraction = NULL;
5589                         if (p->texture_reflection)
5590                                 R_FreeTexture(p->texture_reflection);
5591                         p->texture_reflection = NULL;
5592                         if (p->texture_camera)
5593                                 R_FreeTexture(p->texture_camera);
5594                         p->texture_camera = NULL;
5595                 }
5596                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5597                 r_waterstate.texturewidth = texturewidth;
5598                 r_waterstate.textureheight = textureheight;
5599                 r_waterstate.camerawidth = camerawidth;
5600                 r_waterstate.cameraheight = cameraheight;
5601         }
5602
5603         if (r_waterstate.texturewidth)
5604         {
5605                 int scaledwidth, scaledheight;
5606
5607                 r_waterstate.enabled = true;
5608
5609                 // when doing a reduced render (HDR) we want to use a smaller area
5610                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5611                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5612                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5613
5614                 // set up variables that will be used in shader setup
5615                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5616                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5617                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5618                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5619         }
5620
5621         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5622         r_waterstate.numwaterplanes = 0;
5623 }
5624
5625 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5626 {
5627         int triangleindex, planeindex;
5628         const int *e;
5629         vec3_t vert[3];
5630         vec3_t normal;
5631         vec3_t center;
5632         mplane_t plane;
5633         r_waterstate_waterplane_t *p;
5634         texture_t *t = R_GetCurrentTexture(surface->texture);
5635
5636         // just use the first triangle with a valid normal for any decisions
5637         VectorClear(normal);
5638         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5639         {
5640                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5641                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5642                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5643                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5644                 if (VectorLength2(normal) >= 0.001)
5645                         break;
5646         }
5647
5648         VectorCopy(normal, plane.normal);
5649         VectorNormalize(plane.normal);
5650         plane.dist = DotProduct(vert[0], plane.normal);
5651         PlaneClassify(&plane);
5652         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5653         {
5654                 // skip backfaces (except if nocullface is set)
5655                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5656                         return;
5657                 VectorNegate(plane.normal, plane.normal);
5658                 plane.dist *= -1;
5659                 PlaneClassify(&plane);
5660         }
5661
5662
5663         // find a matching plane if there is one
5664         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5665                 if(p->camera_entity == t->camera_entity)
5666                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5667                                 break;
5668         if (planeindex >= r_waterstate.maxwaterplanes)
5669                 return; // nothing we can do, out of planes
5670
5671         // if this triangle does not fit any known plane rendered this frame, add one
5672         if (planeindex >= r_waterstate.numwaterplanes)
5673         {
5674                 // store the new plane
5675                 r_waterstate.numwaterplanes++;
5676                 p->plane = plane;
5677                 // clear materialflags and pvs
5678                 p->materialflags = 0;
5679                 p->pvsvalid = false;
5680                 p->camera_entity = t->camera_entity;
5681                 VectorCopy(surface->mins, p->mins);
5682                 VectorCopy(surface->maxs, p->maxs);
5683         }
5684         else
5685         {
5686                 // merge mins/maxs
5687                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5688                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5689                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5690                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5691                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5692                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5693         }
5694         // merge this surface's materialflags into the waterplane
5695         p->materialflags |= t->currentmaterialflags;
5696         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5697         {
5698                 // merge this surface's PVS into the waterplane
5699                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5700                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5701                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5702                 {
5703                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5704                         p->pvsvalid = true;
5705                 }
5706         }
5707 }
5708
5709 extern cvar_t r_drawparticles;
5710 extern cvar_t r_drawdecals;
5711
5712 static void R_Water_ProcessPlanes(void)
5713 {
5714         int myscissor[4];
5715         r_refdef_view_t originalview;
5716         r_refdef_view_t myview;
5717         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;
5718         r_waterstate_waterplane_t *p;
5719         vec3_t visorigin;
5720
5721         originalview = r_refdef.view;
5722
5723         // lowquality hack, temporarily shut down some cvars and restore afterwards
5724         qualityreduction = r_water_lowquality.integer;
5725         if (qualityreduction > 0)
5726         {
5727                 if (qualityreduction >= 1)
5728                 {
5729                         old_r_shadows = r_shadows.integer;
5730                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5731                         old_r_dlight = r_shadow_realtime_dlight.integer;
5732                         Cvar_SetValueQuick(&r_shadows, 0);
5733                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5734                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5735                 }
5736                 if (qualityreduction >= 2)
5737                 {
5738                         old_r_dynamic = r_dynamic.integer;
5739                         old_r_particles = r_drawparticles.integer;
5740                         old_r_decals = r_drawdecals.integer;
5741                         Cvar_SetValueQuick(&r_dynamic, 0);
5742                         Cvar_SetValueQuick(&r_drawparticles, 0);
5743                         Cvar_SetValueQuick(&r_drawdecals, 0);
5744                 }
5745         }
5746
5747         // make sure enough textures are allocated
5748         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5749         {
5750                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5751                 {
5752                         if (!p->texture_refraction)
5753                                 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);
5754                         if (!p->texture_refraction)
5755                                 goto error;
5756                 }
5757                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5758                 {
5759                         if (!p->texture_camera)
5760                                 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);
5761                         if (!p->texture_camera)
5762                                 goto error;
5763                 }
5764
5765                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5766                 {
5767                         if (!p->texture_reflection)
5768                                 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);
5769                         if (!p->texture_reflection)
5770                                 goto error;
5771                 }
5772         }
5773
5774         // render views
5775         r_refdef.view = originalview;
5776         r_refdef.view.showdebug = false;
5777         r_refdef.view.width = r_waterstate.waterwidth;
5778         r_refdef.view.height = r_waterstate.waterheight;
5779         r_refdef.view.useclipplane = true;
5780         myview = r_refdef.view;
5781         r_waterstate.renderingscene = true;
5782         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5783         {
5784                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5785                 {
5786                         r_refdef.view = myview;
5787                         if(r_water_scissormode.integer)
5788                         {
5789                                 R_SetupView(true);
5790                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5791                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5792                         }
5793
5794                         // render reflected scene and copy into texture
5795                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5796                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5797                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5798                         r_refdef.view.clipplane = p->plane;
5799                         // reverse the cullface settings for this render
5800                         r_refdef.view.cullface_front = GL_FRONT;
5801                         r_refdef.view.cullface_back = GL_BACK;
5802                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5803                         {
5804                                 r_refdef.view.usecustompvs = true;
5805                                 if (p->pvsvalid)
5806                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5807                                 else
5808                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5809                         }
5810
5811                         R_ResetViewRendering3D();
5812                         R_ClearScreen(r_refdef.fogenabled);
5813                         if(r_water_scissormode.integer & 2)
5814                                 R_View_UpdateWithScissor(myscissor);
5815                         else
5816                                 R_View_Update();
5817                         if(r_water_scissormode.integer & 1)
5818                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5819                         R_RenderScene();
5820
5821                         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);
5822                 }
5823
5824                 // render the normal view scene and copy into texture
5825                 // (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)
5826                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5827                 {
5828                         r_refdef.view = myview;
5829                         if(r_water_scissormode.integer)
5830                         {
5831                                 R_SetupView(true);
5832                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5833                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5834                         }
5835
5836                         r_waterstate.renderingrefraction = true;
5837
5838                         r_refdef.view.clipplane = p->plane;
5839                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5840                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5841
5842                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5843                         {
5844                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5845                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5846                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5847                                 R_RenderView_UpdateViewVectors();
5848                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5849                                 {
5850                                         r_refdef.view.usecustompvs = true;
5851                                         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);
5852                                 }
5853                         }
5854
5855                         PlaneClassify(&r_refdef.view.clipplane);
5856
5857                         R_ResetViewRendering3D();
5858                         R_ClearScreen(r_refdef.fogenabled);
5859                         if(r_water_scissormode.integer & 2)
5860                                 R_View_UpdateWithScissor(myscissor);
5861                         else
5862                                 R_View_Update();
5863                         if(r_water_scissormode.integer & 1)
5864                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5865                         R_RenderScene();
5866
5867                         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);
5868                         r_waterstate.renderingrefraction = false;
5869                 }
5870                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5871                 {
5872                         r_refdef.view = myview;
5873
5874                         r_refdef.view.clipplane = p->plane;
5875                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5876                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5877
5878                         r_refdef.view.width = r_waterstate.camerawidth;
5879                         r_refdef.view.height = r_waterstate.cameraheight;
5880                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5881                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5882
5883                         if(p->camera_entity)
5884                         {
5885                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5886                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5887                         }
5888
5889                         // note: all of the view is used for displaying... so
5890                         // there is no use in scissoring
5891
5892                         // reverse the cullface settings for this render
5893                         r_refdef.view.cullface_front = GL_FRONT;
5894                         r_refdef.view.cullface_back = GL_BACK;
5895                         // also reverse the view matrix
5896                         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
5897                         R_RenderView_UpdateViewVectors();
5898                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5899                         {
5900                                 r_refdef.view.usecustompvs = true;
5901                                 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);
5902                         }
5903                         
5904                         // camera needs no clipplane
5905                         r_refdef.view.useclipplane = false;
5906
5907                         PlaneClassify(&r_refdef.view.clipplane);
5908
5909                         R_ResetViewRendering3D();
5910                         R_ClearScreen(r_refdef.fogenabled);
5911                         R_View_Update();
5912                         R_RenderScene();
5913
5914                         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);
5915                         r_waterstate.renderingrefraction = false;
5916                 }
5917
5918         }
5919         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5920         r_waterstate.renderingscene = false;
5921         r_refdef.view = originalview;
5922         R_ResetViewRendering3D();
5923         R_ClearScreen(r_refdef.fogenabled);
5924         R_View_Update();
5925         goto finish;
5926 error:
5927         r_refdef.view = originalview;
5928         r_waterstate.renderingscene = false;
5929         Cvar_SetValueQuick(&r_water, 0);
5930         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5931 finish:
5932         // lowquality hack, restore cvars
5933         if (qualityreduction > 0)
5934         {
5935                 if (qualityreduction >= 1)
5936                 {
5937                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5938                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5939                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5940                 }
5941                 if (qualityreduction >= 2)
5942                 {
5943                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5944                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5945                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5946                 }
5947         }
5948 }
5949
5950 void R_Bloom_StartFrame(void)
5951 {
5952         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5953         int viewwidth, viewheight;
5954         textype_t textype;
5955
5956         if (r_viewscale_fpsscaling.integer)
5957         {
5958                 double actualframetime;
5959                 double targetframetime;
5960                 double adjust;
5961                 actualframetime = r_refdef.lastdrawscreentime;
5962                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5963                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5964                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5965                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5966                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5967                 viewscalefpsadjusted += adjust;
5968                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5969         }
5970         else
5971                 viewscalefpsadjusted = 1.0f;
5972
5973         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5974
5975         switch(vid.renderpath)
5976         {
5977         case RENDERPATH_GL20:
5978         case RENDERPATH_D3D9:
5979         case RENDERPATH_D3D10:
5980         case RENDERPATH_D3D11:
5981         case RENDERPATH_SOFT:
5982         case RENDERPATH_GLES2:
5983                 break;
5984         case RENDERPATH_GL11:
5985         case RENDERPATH_GL13:
5986         case RENDERPATH_GLES1:
5987                 return;
5988         }
5989
5990         // set bloomwidth and bloomheight to the bloom resolution that will be
5991         // used (often less than the screen resolution for faster rendering)
5992         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5993         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5994         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5995         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5996         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5997
5998         // calculate desired texture sizes
5999         if (vid.support.arb_texture_non_power_of_two)
6000         {
6001                 screentexturewidth = vid.width;
6002                 screentextureheight = vid.height;
6003                 bloomtexturewidth = r_bloomstate.bloomwidth;
6004                 bloomtextureheight = r_bloomstate.bloomheight;
6005         }
6006         else
6007         {
6008                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6009                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6010                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6011                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6012         }
6013
6014         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))
6015         {
6016                 Cvar_SetValueQuick(&r_hdr, 0);
6017                 Cvar_SetValueQuick(&r_bloom, 0);
6018                 Cvar_SetValueQuick(&r_motionblur, 0);
6019                 Cvar_SetValueQuick(&r_damageblur, 0);
6020         }
6021
6022         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)
6023                 screentexturewidth = screentextureheight = 0;
6024         if (!r_hdr.integer && !r_bloom.integer)
6025                 bloomtexturewidth = bloomtextureheight = 0;
6026
6027         textype = TEXTYPE_COLORBUFFER;
6028         switch (vid.renderpath)
6029         {
6030         case RENDERPATH_GL20:
6031         case RENDERPATH_GLES2:
6032                 if (vid.support.ext_framebuffer_object)
6033                 {
6034                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6035                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6036                 }
6037                 break;
6038         case RENDERPATH_GL11:
6039         case RENDERPATH_GL13:
6040         case RENDERPATH_GLES1:
6041         case RENDERPATH_D3D9:
6042         case RENDERPATH_D3D10:
6043         case RENDERPATH_D3D11:
6044         case RENDERPATH_SOFT:
6045                 break;
6046         }
6047
6048         // allocate textures as needed
6049         if (r_bloomstate.screentexturewidth != screentexturewidth
6050          || r_bloomstate.screentextureheight != screentextureheight
6051          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6052          || r_bloomstate.bloomtextureheight != bloomtextureheight
6053          || r_bloomstate.texturetype != textype
6054          || r_bloomstate.viewfbo != r_viewfbo.integer)
6055         {
6056                 if (r_bloomstate.texture_bloom)
6057                         R_FreeTexture(r_bloomstate.texture_bloom);
6058                 r_bloomstate.texture_bloom = NULL;
6059                 if (r_bloomstate.texture_screen)
6060                         R_FreeTexture(r_bloomstate.texture_screen);
6061                 r_bloomstate.texture_screen = NULL;
6062                 if (r_bloomstate.fbo_framebuffer)
6063                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6064                 r_bloomstate.fbo_framebuffer = 0;
6065                 if (r_bloomstate.texture_framebuffercolor)
6066                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6067                 r_bloomstate.texture_framebuffercolor = NULL;
6068                 if (r_bloomstate.texture_framebufferdepth)
6069                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6070                 r_bloomstate.texture_framebufferdepth = NULL;
6071                 r_bloomstate.screentexturewidth = screentexturewidth;
6072                 r_bloomstate.screentextureheight = screentextureheight;
6073                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6074                         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);
6075                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6076                 {
6077                         // FIXME: choose depth bits based on a cvar
6078                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6079                         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);
6080                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6081                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6082 #ifndef USE_GLES2
6083                         // render depth into one texture and normalmap into the other
6084                         if (qglDrawBuffer)
6085                         {
6086                                 int status;
6087                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6088                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6089                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6090                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6091                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6092                         }
6093 #endif
6094                 }
6095                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6096                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6097                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6098                         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);
6099                 r_bloomstate.viewfbo = r_viewfbo.integer;
6100                 r_bloomstate.texturetype = textype;
6101         }
6102
6103         // when doing a reduced render (HDR) we want to use a smaller area
6104         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6105         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6106         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6107         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6108         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6109
6110         // set up a texcoord array for the full resolution screen image
6111         // (we have to keep this around to copy back during final render)
6112         r_bloomstate.screentexcoord2f[0] = 0;
6113         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6114         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6115         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6116         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6117         r_bloomstate.screentexcoord2f[5] = 0;
6118         r_bloomstate.screentexcoord2f[6] = 0;
6119         r_bloomstate.screentexcoord2f[7] = 0;
6120
6121         // set up a texcoord array for the reduced resolution bloom image
6122         // (which will be additive blended over the screen image)
6123         r_bloomstate.bloomtexcoord2f[0] = 0;
6124         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6125         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6126         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6127         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6128         r_bloomstate.bloomtexcoord2f[5] = 0;
6129         r_bloomstate.bloomtexcoord2f[6] = 0;
6130         r_bloomstate.bloomtexcoord2f[7] = 0;
6131
6132         switch(vid.renderpath)
6133         {
6134         case RENDERPATH_GL11:
6135         case RENDERPATH_GL13:
6136         case RENDERPATH_GL20:
6137         case RENDERPATH_SOFT:
6138         case RENDERPATH_GLES1:
6139         case RENDERPATH_GLES2:
6140                 break;
6141         case RENDERPATH_D3D9:
6142         case RENDERPATH_D3D10:
6143         case RENDERPATH_D3D11:
6144                 {
6145                         int i;
6146                         for (i = 0;i < 4;i++)
6147                         {
6148                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6149                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6150                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6151                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6152                         }
6153                 }
6154                 break;
6155         }
6156
6157         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6158         {
6159                 r_bloomstate.enabled = true;
6160                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6161         }
6162
6163         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);
6164
6165         if (r_bloomstate.fbo_framebuffer)
6166                 r_refdef.view.clear = true;
6167 }
6168
6169 void R_Bloom_CopyBloomTexture(float colorscale)
6170 {
6171         r_refdef.stats.bloom++;
6172
6173         // scale down screen texture to the bloom texture size
6174         CHECKGLERROR
6175         R_Mesh_SetMainRenderTargets();
6176         R_SetViewport(&r_bloomstate.viewport);
6177         GL_BlendFunc(GL_ONE, GL_ZERO);
6178         GL_Color(colorscale, colorscale, colorscale, 1);
6179         // 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...
6180         switch(vid.renderpath)
6181         {
6182         case RENDERPATH_GL11:
6183         case RENDERPATH_GL13:
6184         case RENDERPATH_GL20:
6185         case RENDERPATH_GLES1:
6186         case RENDERPATH_GLES2:
6187         case RENDERPATH_SOFT:
6188                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6189                 break;
6190         case RENDERPATH_D3D9:
6191         case RENDERPATH_D3D10:
6192         case RENDERPATH_D3D11:
6193                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6194                 break;
6195         }
6196         // TODO: do boxfilter scale-down in shader?
6197         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6198         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6199         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6200
6201         // we now have a bloom image in the framebuffer
6202         // copy it into the bloom image texture for later processing
6203         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);
6204         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6205 }
6206
6207 void R_Bloom_CopyHDRTexture(void)
6208 {
6209         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);
6210         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6211 }
6212
6213 void R_Bloom_MakeTexture(void)
6214 {
6215         int x, range, dir;
6216         float xoffset, yoffset, r, brighten;
6217
6218         r_refdef.stats.bloom++;
6219
6220         R_ResetViewRendering2D();
6221
6222         // we have a bloom image in the framebuffer
6223         CHECKGLERROR
6224         R_SetViewport(&r_bloomstate.viewport);
6225
6226         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6227         {
6228                 x *= 2;
6229                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6230                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6231                 GL_Color(r,r,r,1);
6232                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6233                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6234                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6235                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6236
6237                 // copy the vertically blurred bloom view to a texture
6238                 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);
6239                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6240         }
6241
6242         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6243         brighten = r_bloom_brighten.value;
6244         if (r_bloomstate.hdr)
6245                 brighten *= r_hdr_range.value;
6246         brighten = sqrt(brighten);
6247         if(range >= 1)
6248                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6249         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6250
6251         for (dir = 0;dir < 2;dir++)
6252         {
6253                 // blend on at multiple vertical offsets to achieve a vertical blur
6254                 // TODO: do offset blends using GLSL
6255                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6256                 GL_BlendFunc(GL_ONE, GL_ZERO);
6257                 for (x = -range;x <= range;x++)
6258                 {
6259                         if (!dir){xoffset = 0;yoffset = x;}
6260                         else {xoffset = x;yoffset = 0;}
6261                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6262                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6263                         // compute a texcoord array with the specified x and y offset
6264                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6265                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6266                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6267                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6268                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6269                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6270                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6271                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6272                         // this r value looks like a 'dot' particle, fading sharply to
6273                         // black at the edges
6274                         // (probably not realistic but looks good enough)
6275                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6276                         //r = brighten/(range*2+1);
6277                         r = brighten / (range * 2 + 1);
6278                         if(range >= 1)
6279                                 r *= (1 - x*x/(float)(range*range));
6280                         GL_Color(r, r, r, 1);
6281                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6282                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6283                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6284                         GL_BlendFunc(GL_ONE, GL_ONE);
6285                 }
6286
6287                 // copy the vertically blurred bloom view to a texture
6288                 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);
6289                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6290         }
6291 }
6292
6293 void R_HDR_RenderBloomTexture(void)
6294 {
6295         int oldwidth, oldheight;
6296         float oldcolorscale;
6297         qboolean oldwaterstate;
6298
6299         oldwaterstate = r_waterstate.enabled;
6300         oldcolorscale = r_refdef.view.colorscale;
6301         oldwidth = r_refdef.view.width;
6302         oldheight = r_refdef.view.height;
6303         r_refdef.view.width = r_bloomstate.bloomwidth;
6304         r_refdef.view.height = r_bloomstate.bloomheight;
6305
6306         if(r_hdr.integer < 2)
6307                 r_waterstate.enabled = false;
6308
6309         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6310         // TODO: add exposure compensation features
6311         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6312
6313         r_refdef.view.showdebug = false;
6314         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6315
6316         R_ResetViewRendering3D();
6317
6318         R_ClearScreen(r_refdef.fogenabled);
6319         if (r_timereport_active)
6320                 R_TimeReport("HDRclear");
6321
6322         R_View_Update();
6323         if (r_timereport_active)
6324                 R_TimeReport("visibility");
6325
6326         // only do secondary renders with HDR if r_hdr is 2 or higher
6327         r_waterstate.numwaterplanes = 0;
6328         if (r_waterstate.enabled)
6329                 R_RenderWaterPlanes();
6330
6331         r_refdef.view.showdebug = true;
6332         R_RenderScene();
6333         r_waterstate.numwaterplanes = 0;
6334
6335         R_ResetViewRendering2D();
6336
6337         R_Bloom_CopyHDRTexture();
6338         R_Bloom_MakeTexture();
6339
6340         // restore the view settings
6341         r_waterstate.enabled = oldwaterstate;
6342         r_refdef.view.width = oldwidth;
6343         r_refdef.view.height = oldheight;
6344         r_refdef.view.colorscale = oldcolorscale;
6345
6346         R_ResetViewRendering3D();
6347
6348         R_ClearScreen(r_refdef.fogenabled);
6349         if (r_timereport_active)
6350                 R_TimeReport("viewclear");
6351 }
6352
6353 static void R_BlendView(void)
6354 {
6355         unsigned int permutation;
6356         float uservecs[4][4];
6357
6358         switch (vid.renderpath)
6359         {
6360         case RENDERPATH_GL20:
6361         case RENDERPATH_D3D9:
6362         case RENDERPATH_D3D10:
6363         case RENDERPATH_D3D11:
6364         case RENDERPATH_SOFT:
6365         case RENDERPATH_GLES2:
6366                 permutation =
6367                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6368                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6369                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6370                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6371                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6372
6373                 if (r_bloomstate.texture_screen)
6374                 {
6375                         // make sure the buffer is available
6376                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6377
6378                         R_ResetViewRendering2D();
6379                         R_Mesh_SetMainRenderTargets();
6380
6381                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6382                         {
6383                                 // declare variables
6384                                 float blur_factor, blur_mouseaccel, blur_velocity;
6385                                 static float blur_average; 
6386                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6387
6388                                 // set a goal for the factoring
6389                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6390                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6391                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6392                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6393                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6394                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6395
6396                                 // from the goal, pick an averaged value between goal and last value
6397                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6398                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6399                                 
6400                                 // enforce minimum amount of blur 
6401                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6402                                 
6403                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6404
6405                                 // calculate values into a standard alpha
6406                                 cl.motionbluralpha = 1 - exp(-
6407                                                 (
6408                                                  (r_motionblur.value * blur_factor / 80)
6409                                                  +
6410                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6411                                                 )
6412                                                 /
6413                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6414                                           );
6415                                 
6416                                 // randomization for the blur value to combat persistent ghosting
6417                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6418                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6419                                 
6420                                 // apply the blur
6421                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6422                                 {
6423                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6424                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6425                                         switch(vid.renderpath)
6426                                         {
6427                                         case RENDERPATH_GL11:
6428                                         case RENDERPATH_GL13:
6429                                         case RENDERPATH_GL20:
6430                                         case RENDERPATH_GLES1:
6431                                         case RENDERPATH_GLES2:
6432                                         case RENDERPATH_SOFT:
6433                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6434                                                 break;
6435                                         case RENDERPATH_D3D9:
6436                                         case RENDERPATH_D3D10:
6437                                         case RENDERPATH_D3D11:
6438                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6439                                                 break;
6440                                         }
6441                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6442                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6443                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6444                                 }
6445                                 
6446                                 // updates old view angles for next pass 
6447                                 VectorCopy(cl.viewangles, blur_oldangles);
6448                         }
6449
6450                         // copy view into the screen texture
6451                         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);
6452                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6453                 }
6454                 else if (!r_bloomstate.texture_bloom)
6455                 {
6456                         // we may still have to do view tint...
6457                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6458                         {
6459                                 // apply a color tint to the whole view
6460                                 R_ResetViewRendering2D();
6461                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6462                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6463                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6464                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6465                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6466                         }
6467                         break; // no screen processing, no bloom, skip it
6468                 }
6469
6470                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6471                 {
6472                         // render simple bloom effect
6473                         // copy the screen and shrink it and darken it for the bloom process
6474                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6475                         // make the bloom texture
6476                         R_Bloom_MakeTexture();
6477                 }
6478
6479 #if _MSC_VER >= 1400
6480 #define sscanf sscanf_s
6481 #endif
6482                 memset(uservecs, 0, sizeof(uservecs));
6483                 if (r_glsl_postprocess_uservec1_enable.integer)
6484                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6485                 if (r_glsl_postprocess_uservec2_enable.integer)
6486                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6487                 if (r_glsl_postprocess_uservec3_enable.integer)
6488                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6489                 if (r_glsl_postprocess_uservec4_enable.integer)
6490                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6491
6492                 R_ResetViewRendering2D();
6493                 GL_Color(1, 1, 1, 1);
6494                 GL_BlendFunc(GL_ONE, GL_ZERO);
6495
6496                 switch(vid.renderpath)
6497                 {
6498                 case RENDERPATH_GL20:
6499                 case RENDERPATH_GLES2:
6500                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6501                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6502                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6503                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6504                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6505                         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]);
6506                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6507                         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]);
6508                         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]);
6509                         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]);
6510                         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]);
6511                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6512                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6513                         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);
6514                         break;
6515                 case RENDERPATH_D3D9:
6516 #ifdef SUPPORTD3D
6517                         // 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...
6518                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6519                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6520                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6521                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6522                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6523                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6524                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6525                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6526                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6527                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6528                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6529                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6530                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6531                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6532 #endif
6533                         break;
6534                 case RENDERPATH_D3D10:
6535                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6536                         break;
6537                 case RENDERPATH_D3D11:
6538                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6539                         break;
6540                 case RENDERPATH_SOFT:
6541                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6542                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6543                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6544                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6545                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6546                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6547                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6548                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6549                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6550                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6551                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6552                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6553                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6554                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6555                         break;
6556                 default:
6557                         break;
6558                 }
6559                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6560                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6561                 break;
6562         case RENDERPATH_GL11:
6563         case RENDERPATH_GL13:
6564         case RENDERPATH_GLES1:
6565                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6566                 {
6567                         // apply a color tint to the whole view
6568                         R_ResetViewRendering2D();
6569                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6570                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6571                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6572                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6573                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6574                 }
6575                 break;
6576         }
6577 }
6578
6579 matrix4x4_t r_waterscrollmatrix;
6580
6581 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6582 {
6583         if (r_refdef.fog_density)
6584         {
6585                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6586                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6587                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6588
6589                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6590                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6591                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6592                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6593
6594                 {
6595                         vec3_t fogvec;
6596                         VectorCopy(r_refdef.fogcolor, fogvec);
6597                         //   color.rgb *= ContrastBoost * SceneBrightness;
6598                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6599                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6600                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6601                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6602                 }
6603         }
6604 }
6605
6606 void R_UpdateVariables(void)
6607 {
6608         R_Textures_Frame();
6609
6610         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6611
6612         r_refdef.farclip = r_farclip_base.value;
6613         if (r_refdef.scene.worldmodel)
6614                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6615         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6616
6617         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6618                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6619         r_refdef.polygonfactor = 0;
6620         r_refdef.polygonoffset = 0;
6621         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6622         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6623
6624         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6625         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6626         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6627         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6628         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6629         if (FAKELIGHT_ENABLED)
6630         {
6631                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6632         }
6633         if (r_showsurfaces.integer)
6634         {
6635                 r_refdef.scene.rtworld = false;
6636                 r_refdef.scene.rtworldshadows = false;
6637                 r_refdef.scene.rtdlight = false;
6638                 r_refdef.scene.rtdlightshadows = false;
6639                 r_refdef.lightmapintensity = 0;
6640         }
6641
6642         if (gamemode == GAME_NEHAHRA)
6643         {
6644                 if (gl_fogenable.integer)
6645                 {
6646                         r_refdef.oldgl_fogenable = true;
6647                         r_refdef.fog_density = gl_fogdensity.value;
6648                         r_refdef.fog_red = gl_fogred.value;
6649                         r_refdef.fog_green = gl_foggreen.value;
6650                         r_refdef.fog_blue = gl_fogblue.value;
6651                         r_refdef.fog_alpha = 1;
6652                         r_refdef.fog_start = 0;
6653                         r_refdef.fog_end = gl_skyclip.value;
6654                         r_refdef.fog_height = 1<<30;
6655                         r_refdef.fog_fadedepth = 128;
6656                 }
6657                 else if (r_refdef.oldgl_fogenable)
6658                 {
6659                         r_refdef.oldgl_fogenable = false;
6660                         r_refdef.fog_density = 0;
6661                         r_refdef.fog_red = 0;
6662                         r_refdef.fog_green = 0;
6663                         r_refdef.fog_blue = 0;
6664                         r_refdef.fog_alpha = 0;
6665                         r_refdef.fog_start = 0;
6666                         r_refdef.fog_end = 0;
6667                         r_refdef.fog_height = 1<<30;
6668                         r_refdef.fog_fadedepth = 128;
6669                 }
6670         }
6671
6672         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6673         r_refdef.fog_start = max(0, r_refdef.fog_start);
6674         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6675
6676         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6677
6678         if (r_refdef.fog_density && r_drawfog.integer)
6679         {
6680                 r_refdef.fogenabled = true;
6681                 // this is the point where the fog reaches 0.9986 alpha, which we
6682                 // consider a good enough cutoff point for the texture
6683                 // (0.9986 * 256 == 255.6)
6684                 if (r_fog_exp2.integer)
6685                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6686                 else
6687                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6688                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6689                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6690                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6691                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6692                         R_BuildFogHeightTexture();
6693                 // fog color was already set
6694                 // update the fog texture
6695                 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)
6696                         R_BuildFogTexture();
6697                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6698                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6699         }
6700         else
6701                 r_refdef.fogenabled = false;
6702
6703         switch(vid.renderpath)
6704         {
6705         case RENDERPATH_GL20:
6706         case RENDERPATH_D3D9:
6707         case RENDERPATH_D3D10:
6708         case RENDERPATH_D3D11:
6709         case RENDERPATH_SOFT:
6710         case RENDERPATH_GLES2:
6711                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6712                 {
6713                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6714                         {
6715                                 // build GLSL gamma texture
6716 #define RAMPWIDTH 256
6717                                 unsigned short ramp[RAMPWIDTH * 3];
6718                                 unsigned char rampbgr[RAMPWIDTH][4];
6719                                 int i;
6720
6721                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6722
6723                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6724                                 for(i = 0; i < RAMPWIDTH; ++i)
6725                                 {
6726                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6727                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6728                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6729                                         rampbgr[i][3] = 0;
6730                                 }
6731                                 if (r_texture_gammaramps)
6732                                 {
6733                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6734                                 }
6735                                 else
6736                                 {
6737                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6738                                 }
6739                         }
6740                 }
6741                 else
6742                 {
6743                         // remove GLSL gamma texture
6744                 }
6745                 break;
6746         case RENDERPATH_GL11:
6747         case RENDERPATH_GL13:
6748         case RENDERPATH_GLES1:
6749                 break;
6750         }
6751 }
6752
6753 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6754 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6755 /*
6756 ================
6757 R_SelectScene
6758 ================
6759 */
6760 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6761         if( scenetype != r_currentscenetype ) {
6762                 // store the old scenetype
6763                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6764                 r_currentscenetype = scenetype;
6765                 // move in the new scene
6766                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6767         }
6768 }
6769
6770 /*
6771 ================
6772 R_GetScenePointer
6773 ================
6774 */
6775 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6776 {
6777         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6778         if( scenetype == r_currentscenetype ) {
6779                 return &r_refdef.scene;
6780         } else {
6781                 return &r_scenes_store[ scenetype ];
6782         }
6783 }
6784
6785 int R_SortEntities_Compare(const void *ap, const void *bp)
6786 {
6787         const entity_render_t *a = *(const entity_render_t **)ap;
6788         const entity_render_t *b = *(const entity_render_t **)bp;
6789
6790         // 1. compare model
6791         if(a->model < b->model)
6792                 return -1;
6793         if(a->model > b->model)
6794                 return +1;
6795
6796         // 2. compare skin
6797         // TODO possibly calculate the REAL skinnum here first using
6798         // skinscenes?
6799         if(a->skinnum < b->skinnum)
6800                 return -1;
6801         if(a->skinnum > b->skinnum)
6802                 return +1;
6803
6804         // everything we compared is equal
6805         return 0;
6806 }
6807 void R_SortEntities(void)
6808 {
6809         // below or equal 2 ents, sorting never gains anything
6810         if(r_refdef.scene.numentities <= 2)
6811                 return;
6812         // sort
6813         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6814 }
6815
6816 /*
6817 ================
6818 R_RenderView
6819 ================
6820 */
6821 int dpsoftrast_test;
6822 extern void R_Shadow_UpdateBounceGridTexture(void);
6823 extern cvar_t r_shadow_bouncegrid;
6824 void R_RenderView(void)
6825 {
6826         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6827
6828         dpsoftrast_test = r_test.integer;
6829
6830         if (r_timereport_active)
6831                 R_TimeReport("start");
6832         r_textureframe++; // used only by R_GetCurrentTexture
6833         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6834
6835         if(R_CompileShader_CheckStaticParms())
6836                 R_GLSL_Restart_f();
6837
6838         if (!r_drawentities.integer)
6839                 r_refdef.scene.numentities = 0;
6840         else if (r_sortentities.integer)
6841                 R_SortEntities();
6842
6843         R_AnimCache_ClearCache();
6844         R_FrameData_NewFrame();
6845
6846         /* adjust for stereo display */
6847         if(R_Stereo_Active())
6848         {
6849                 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);
6850                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6851         }
6852
6853         if (r_refdef.view.isoverlay)
6854         {
6855                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6856                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6857                 R_TimeReport("depthclear");
6858
6859                 r_refdef.view.showdebug = false;
6860
6861                 r_waterstate.enabled = false;
6862                 r_waterstate.numwaterplanes = 0;
6863
6864                 R_RenderScene();
6865
6866                 r_refdef.view.matrix = originalmatrix;
6867
6868                 CHECKGLERROR
6869                 return;
6870         }
6871
6872         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6873         {
6874                 r_refdef.view.matrix = originalmatrix;
6875                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6876         }
6877
6878         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6879
6880         R_RenderView_UpdateViewVectors();
6881
6882         R_Shadow_UpdateWorldLightSelection();
6883
6884         R_Bloom_StartFrame();
6885         R_Water_StartFrame();
6886
6887         CHECKGLERROR
6888         if (r_timereport_active)
6889                 R_TimeReport("viewsetup");
6890
6891         R_ResetViewRendering3D();
6892
6893         if (r_refdef.view.clear || r_refdef.fogenabled)
6894         {
6895                 R_ClearScreen(r_refdef.fogenabled);
6896                 if (r_timereport_active)
6897                         R_TimeReport("viewclear");
6898         }
6899         r_refdef.view.clear = true;
6900
6901         // this produces a bloom texture to be used in R_BlendView() later
6902         if (r_bloomstate.hdr)
6903         {
6904                 R_HDR_RenderBloomTexture();
6905                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6906                 r_textureframe++; // used only by R_GetCurrentTexture
6907         }
6908
6909         r_refdef.view.showdebug = true;
6910
6911         R_View_Update();
6912         if (r_timereport_active)
6913                 R_TimeReport("visibility");
6914
6915         R_Shadow_UpdateBounceGridTexture();
6916         if (r_timereport_active && r_shadow_bouncegrid.integer)
6917                 R_TimeReport("bouncegrid");
6918
6919         r_waterstate.numwaterplanes = 0;
6920         if (r_waterstate.enabled)
6921                 R_RenderWaterPlanes();
6922
6923         R_RenderScene();
6924         r_waterstate.numwaterplanes = 0;
6925
6926         R_BlendView();
6927         if (r_timereport_active)
6928                 R_TimeReport("blendview");
6929
6930         GL_Scissor(0, 0, vid.width, vid.height);
6931         GL_ScissorTest(false);
6932
6933         r_refdef.view.matrix = originalmatrix;
6934
6935         CHECKGLERROR
6936 }
6937
6938 void R_RenderWaterPlanes(void)
6939 {
6940         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6941         {
6942                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6943                 if (r_timereport_active)
6944                         R_TimeReport("waterworld");
6945         }
6946
6947         // don't let sound skip if going slow
6948         if (r_refdef.scene.extraupdate)
6949                 S_ExtraUpdate ();
6950
6951         R_DrawModelsAddWaterPlanes();
6952         if (r_timereport_active)
6953                 R_TimeReport("watermodels");
6954
6955         if (r_waterstate.numwaterplanes)
6956         {
6957                 R_Water_ProcessPlanes();
6958                 if (r_timereport_active)
6959                         R_TimeReport("waterscenes");
6960         }
6961 }
6962
6963 extern void R_DrawLightningBeams (void);
6964 extern void VM_CL_AddPolygonsToMeshQueue (void);
6965 extern void R_DrawPortals (void);
6966 extern cvar_t cl_locs_show;
6967 static void R_DrawLocs(void);
6968 static void R_DrawEntityBBoxes(void);
6969 static void R_DrawModelDecals(void);
6970 extern void R_DrawModelShadows(void);
6971 extern void R_DrawModelShadowMaps(void);
6972 extern cvar_t cl_decals_newsystem;
6973 extern qboolean r_shadow_usingdeferredprepass;
6974 void R_RenderScene(void)
6975 {
6976         qboolean shadowmapping = false;
6977
6978         if (r_timereport_active)
6979                 R_TimeReport("beginscene");
6980
6981         r_refdef.stats.renders++;
6982
6983         R_UpdateFogColor();
6984
6985         // don't let sound skip if going slow
6986         if (r_refdef.scene.extraupdate)
6987                 S_ExtraUpdate ();
6988
6989         R_MeshQueue_BeginScene();
6990
6991         R_SkyStartFrame();
6992
6993         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);
6994
6995         if (r_timereport_active)
6996                 R_TimeReport("skystartframe");
6997
6998         if (cl.csqc_vidvars.drawworld)
6999         {
7000                 // don't let sound skip if going slow
7001                 if (r_refdef.scene.extraupdate)
7002                         S_ExtraUpdate ();
7003
7004                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7005                 {
7006                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7007                         if (r_timereport_active)
7008                                 R_TimeReport("worldsky");
7009                 }
7010
7011                 if (R_DrawBrushModelsSky() && r_timereport_active)
7012                         R_TimeReport("bmodelsky");
7013
7014                 if (skyrendermasked && skyrenderlater)
7015                 {
7016                         // we have to force off the water clipping plane while rendering sky
7017                         R_SetupView(false);
7018                         R_Sky();
7019                         R_SetupView(true);
7020                         if (r_timereport_active)
7021                                 R_TimeReport("sky");
7022                 }
7023         }
7024
7025         R_AnimCache_CacheVisibleEntities();
7026         if (r_timereport_active)
7027                 R_TimeReport("animation");
7028
7029         R_Shadow_PrepareLights();
7030         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7031                 R_Shadow_PrepareModelShadows();
7032         if (r_timereport_active)
7033                 R_TimeReport("preparelights");
7034
7035         if (R_Shadow_ShadowMappingEnabled())
7036                 shadowmapping = true;
7037
7038         if (r_shadow_usingdeferredprepass)
7039                 R_Shadow_DrawPrepass();
7040
7041         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7042         {
7043                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7044                 if (r_timereport_active)
7045                         R_TimeReport("worlddepth");
7046         }
7047         if (r_depthfirst.integer >= 2)
7048         {
7049                 R_DrawModelsDepth();
7050                 if (r_timereport_active)
7051                         R_TimeReport("modeldepth");
7052         }
7053
7054         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7055         {
7056                 R_DrawModelShadowMaps();
7057                 R_ResetViewRendering3D();
7058                 // don't let sound skip if going slow
7059                 if (r_refdef.scene.extraupdate)
7060                         S_ExtraUpdate ();
7061         }
7062
7063         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7064         {
7065                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7066                 if (r_timereport_active)
7067                         R_TimeReport("world");
7068         }
7069
7070         // don't let sound skip if going slow
7071         if (r_refdef.scene.extraupdate)
7072                 S_ExtraUpdate ();
7073
7074         R_DrawModels();
7075         if (r_timereport_active)
7076                 R_TimeReport("models");
7077
7078         // don't let sound skip if going slow
7079         if (r_refdef.scene.extraupdate)
7080                 S_ExtraUpdate ();
7081
7082         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7083         {
7084                 R_DrawModelShadows();
7085                 R_ResetViewRendering3D();
7086                 // don't let sound skip if going slow
7087                 if (r_refdef.scene.extraupdate)
7088                         S_ExtraUpdate ();
7089         }
7090
7091         if (!r_shadow_usingdeferredprepass)
7092         {
7093                 R_Shadow_DrawLights();
7094                 if (r_timereport_active)
7095                         R_TimeReport("rtlights");
7096         }
7097
7098         // don't let sound skip if going slow
7099         if (r_refdef.scene.extraupdate)
7100                 S_ExtraUpdate ();
7101
7102         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7103         {
7104                 R_DrawModelShadows();
7105                 R_ResetViewRendering3D();
7106                 // don't let sound skip if going slow
7107                 if (r_refdef.scene.extraupdate)
7108                         S_ExtraUpdate ();
7109         }
7110
7111         if (cl.csqc_vidvars.drawworld)
7112         {
7113                 if (cl_decals_newsystem.integer)
7114                 {
7115                         R_DrawModelDecals();
7116                         if (r_timereport_active)
7117                                 R_TimeReport("modeldecals");
7118                 }
7119                 else
7120                 {
7121                         R_DrawDecals();
7122                         if (r_timereport_active)
7123                                 R_TimeReport("decals");
7124                 }
7125
7126                 R_DrawParticles();
7127                 if (r_timereport_active)
7128                         R_TimeReport("particles");
7129
7130                 R_DrawExplosions();
7131                 if (r_timereport_active)
7132                         R_TimeReport("explosions");
7133
7134                 R_DrawLightningBeams();
7135                 if (r_timereport_active)
7136                         R_TimeReport("lightning");
7137         }
7138
7139         VM_CL_AddPolygonsToMeshQueue();
7140
7141         if (r_refdef.view.showdebug)
7142         {
7143                 if (cl_locs_show.integer)
7144                 {
7145                         R_DrawLocs();
7146                         if (r_timereport_active)
7147                                 R_TimeReport("showlocs");
7148                 }
7149
7150                 if (r_drawportals.integer)
7151                 {
7152                         R_DrawPortals();
7153                         if (r_timereport_active)
7154                                 R_TimeReport("portals");
7155                 }
7156
7157                 if (r_showbboxes.value > 0)
7158                 {
7159                         R_DrawEntityBBoxes();
7160                         if (r_timereport_active)
7161                                 R_TimeReport("bboxes");
7162                 }
7163         }
7164
7165         if (r_transparent.integer)
7166         {
7167                 R_MeshQueue_RenderTransparent();
7168                 if (r_timereport_active)
7169                         R_TimeReport("drawtrans");
7170         }
7171
7172         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))
7173         {
7174                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7175                 if (r_timereport_active)
7176                         R_TimeReport("worlddebug");
7177                 R_DrawModelsDebug();
7178                 if (r_timereport_active)
7179                         R_TimeReport("modeldebug");
7180         }
7181
7182         if (cl.csqc_vidvars.drawworld)
7183         {
7184                 R_Shadow_DrawCoronas();
7185                 if (r_timereport_active)
7186                         R_TimeReport("coronas");
7187         }
7188
7189 #if 0
7190         {
7191                 GL_DepthTest(false);
7192                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7193                 GL_Color(1, 1, 1, 1);
7194                 qglBegin(GL_POLYGON);
7195                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7196                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7197                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7198                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7199                 qglEnd();
7200                 qglBegin(GL_POLYGON);
7201                 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]);
7202                 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]);
7203                 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]);
7204                 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]);
7205                 qglEnd();
7206                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7207         }
7208 #endif
7209
7210         // don't let sound skip if going slow
7211         if (r_refdef.scene.extraupdate)
7212                 S_ExtraUpdate ();
7213
7214         R_ResetViewRendering2D();
7215 }
7216
7217 static const unsigned short bboxelements[36] =
7218 {
7219         5, 1, 3, 5, 3, 7,
7220         6, 2, 0, 6, 0, 4,
7221         7, 3, 2, 7, 2, 6,
7222         4, 0, 1, 4, 1, 5,
7223         4, 5, 7, 4, 7, 6,
7224         1, 0, 2, 1, 2, 3,
7225 };
7226
7227 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7228 {
7229         int i;
7230         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7231
7232         RSurf_ActiveWorldEntity();
7233
7234         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7235         GL_DepthMask(false);
7236         GL_DepthRange(0, 1);
7237         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7238 //      R_Mesh_ResetTextureState();
7239
7240         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7241         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7242         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7243         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7244         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7245         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7246         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7247         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7248         R_FillColors(color4f, 8, cr, cg, cb, ca);
7249         if (r_refdef.fogenabled)
7250         {
7251                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7252                 {
7253                         f1 = RSurf_FogVertex(v);
7254                         f2 = 1 - f1;
7255                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7256                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7257                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7258                 }
7259         }
7260         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7261         R_Mesh_ResetTextureState();
7262         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7263         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7264 }
7265
7266 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7267 {
7268         int i;
7269         float color[4];
7270         prvm_edict_t *edict;
7271         prvm_prog_t *prog_save = prog;
7272
7273         // this function draws bounding boxes of server entities
7274         if (!sv.active)
7275                 return;
7276
7277         GL_CullFace(GL_NONE);
7278         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7279
7280         prog = 0;
7281         SV_VM_Begin();
7282         for (i = 0;i < numsurfaces;i++)
7283         {
7284                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7285                 switch ((int)PRVM_serveredictfloat(edict, solid))
7286                 {
7287                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7288                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7289                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7290                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7291                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7292                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7293                 }
7294                 color[3] *= r_showbboxes.value;
7295                 color[3] = bound(0, color[3], 1);
7296                 GL_DepthTest(!r_showdisabledepthtest.integer);
7297                 GL_CullFace(r_refdef.view.cullface_front);
7298                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7299         }
7300         SV_VM_End();
7301         prog = prog_save;
7302 }
7303
7304 static void R_DrawEntityBBoxes(void)
7305 {
7306         int i;
7307         prvm_edict_t *edict;
7308         vec3_t center;
7309         prvm_prog_t *prog_save = prog;
7310
7311         // this function draws bounding boxes of server entities
7312         if (!sv.active)
7313                 return;
7314
7315         prog = 0;
7316         SV_VM_Begin();
7317         for (i = 0;i < prog->num_edicts;i++)
7318         {
7319                 edict = PRVM_EDICT_NUM(i);
7320                 if (edict->priv.server->free)
7321                         continue;
7322                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7323                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7324                         continue;
7325                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7326                         continue;
7327                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7328                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7329         }
7330         SV_VM_End();
7331         prog = prog_save;
7332 }
7333
7334 static const int nomodelelement3i[24] =
7335 {
7336         5, 2, 0,
7337         5, 1, 2,
7338         5, 0, 3,
7339         5, 3, 1,
7340         0, 2, 4,
7341         2, 1, 4,
7342         3, 0, 4,
7343         1, 3, 4
7344 };
7345
7346 static const unsigned short nomodelelement3s[24] =
7347 {
7348         5, 2, 0,
7349         5, 1, 2,
7350         5, 0, 3,
7351         5, 3, 1,
7352         0, 2, 4,
7353         2, 1, 4,
7354         3, 0, 4,
7355         1, 3, 4
7356 };
7357
7358 static const float nomodelvertex3f[6*3] =
7359 {
7360         -16,   0,   0,
7361          16,   0,   0,
7362           0, -16,   0,
7363           0,  16,   0,
7364           0,   0, -16,
7365           0,   0,  16
7366 };
7367
7368 static const float nomodelcolor4f[6*4] =
7369 {
7370         0.0f, 0.0f, 0.5f, 1.0f,
7371         0.0f, 0.0f, 0.5f, 1.0f,
7372         0.0f, 0.5f, 0.0f, 1.0f,
7373         0.0f, 0.5f, 0.0f, 1.0f,
7374         0.5f, 0.0f, 0.0f, 1.0f,
7375         0.5f, 0.0f, 0.0f, 1.0f
7376 };
7377
7378 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7379 {
7380         int i;
7381         float f1, f2, *c;
7382         float color4f[6*4];
7383
7384         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);
7385
7386         // this is only called once per entity so numsurfaces is always 1, and
7387         // surfacelist is always {0}, so this code does not handle batches
7388
7389         if (rsurface.ent_flags & RENDER_ADDITIVE)
7390         {
7391                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7392                 GL_DepthMask(false);
7393         }
7394         else if (rsurface.colormod[3] < 1)
7395         {
7396                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7397                 GL_DepthMask(false);
7398         }
7399         else
7400         {
7401                 GL_BlendFunc(GL_ONE, GL_ZERO);
7402                 GL_DepthMask(true);
7403         }
7404         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7405         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7406         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7407         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7408         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7409         for (i = 0, c = color4f;i < 6;i++, c += 4)
7410         {
7411                 c[0] *= rsurface.colormod[0];
7412                 c[1] *= rsurface.colormod[1];
7413                 c[2] *= rsurface.colormod[2];
7414                 c[3] *= rsurface.colormod[3];
7415         }
7416         if (r_refdef.fogenabled)
7417         {
7418                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7419                 {
7420                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7421                         f2 = 1 - f1;
7422                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7423                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7424                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7425                 }
7426         }
7427 //      R_Mesh_ResetTextureState();
7428         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7429         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7430         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7431 }
7432
7433 void R_DrawNoModel(entity_render_t *ent)
7434 {
7435         vec3_t org;
7436         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7437         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7438                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7439         else
7440                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7441 }
7442
7443 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7444 {
7445         vec3_t right1, right2, diff, normal;
7446
7447         VectorSubtract (org2, org1, normal);
7448
7449         // calculate 'right' vector for start
7450         VectorSubtract (r_refdef.view.origin, org1, diff);
7451         CrossProduct (normal, diff, right1);
7452         VectorNormalize (right1);
7453
7454         // calculate 'right' vector for end
7455         VectorSubtract (r_refdef.view.origin, org2, diff);
7456         CrossProduct (normal, diff, right2);
7457         VectorNormalize (right2);
7458
7459         vert[ 0] = org1[0] + width * right1[0];
7460         vert[ 1] = org1[1] + width * right1[1];
7461         vert[ 2] = org1[2] + width * right1[2];
7462         vert[ 3] = org1[0] - width * right1[0];
7463         vert[ 4] = org1[1] - width * right1[1];
7464         vert[ 5] = org1[2] - width * right1[2];
7465         vert[ 6] = org2[0] - width * right2[0];
7466         vert[ 7] = org2[1] - width * right2[1];
7467         vert[ 8] = org2[2] - width * right2[2];
7468         vert[ 9] = org2[0] + width * right2[0];
7469         vert[10] = org2[1] + width * right2[1];
7470         vert[11] = org2[2] + width * right2[2];
7471 }
7472
7473 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)
7474 {
7475         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7476         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7477         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7478         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7479         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7480         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7481         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7482         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7483         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7484         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7485         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7486         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7487 }
7488
7489 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7490 {
7491         int i;
7492         float *vertex3f;
7493         float v[3];
7494         VectorSet(v, x, y, z);
7495         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7496                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7497                         break;
7498         if (i == mesh->numvertices)
7499         {
7500                 if (mesh->numvertices < mesh->maxvertices)
7501                 {
7502                         VectorCopy(v, vertex3f);
7503                         mesh->numvertices++;
7504                 }
7505                 return mesh->numvertices;
7506         }
7507         else
7508                 return i;
7509 }
7510
7511 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7512 {
7513         int i;
7514         int *e, element[3];
7515         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7516         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7517         e = mesh->element3i + mesh->numtriangles * 3;
7518         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7519         {
7520                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7521                 if (mesh->numtriangles < mesh->maxtriangles)
7522                 {
7523                         *e++ = element[0];
7524                         *e++ = element[1];
7525                         *e++ = element[2];
7526                         mesh->numtriangles++;
7527                 }
7528                 element[1] = element[2];
7529         }
7530 }
7531
7532 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7533 {
7534         int i;
7535         int *e, element[3];
7536         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7537         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7538         e = mesh->element3i + mesh->numtriangles * 3;
7539         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7540         {
7541                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7542                 if (mesh->numtriangles < mesh->maxtriangles)
7543                 {
7544                         *e++ = element[0];
7545                         *e++ = element[1];
7546                         *e++ = element[2];
7547                         mesh->numtriangles++;
7548                 }
7549                 element[1] = element[2];
7550         }
7551 }
7552
7553 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7554 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7555 {
7556         int planenum, planenum2;
7557         int w;
7558         int tempnumpoints;
7559         mplane_t *plane, *plane2;
7560         double maxdist;
7561         double temppoints[2][256*3];
7562         // figure out how large a bounding box we need to properly compute this brush
7563         maxdist = 0;
7564         for (w = 0;w < numplanes;w++)
7565                 maxdist = max(maxdist, fabs(planes[w].dist));
7566         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7567         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7568         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7569         {
7570                 w = 0;
7571                 tempnumpoints = 4;
7572                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7573                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7574                 {
7575                         if (planenum2 == planenum)
7576                                 continue;
7577                         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);
7578                         w = !w;
7579                 }
7580                 if (tempnumpoints < 3)
7581                         continue;
7582                 // generate elements forming a triangle fan for this polygon
7583                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7584         }
7585 }
7586
7587 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)
7588 {
7589         texturelayer_t *layer;
7590         layer = t->currentlayers + t->currentnumlayers++;
7591         layer->type = type;
7592         layer->depthmask = depthmask;
7593         layer->blendfunc1 = blendfunc1;
7594         layer->blendfunc2 = blendfunc2;
7595         layer->texture = texture;
7596         layer->texmatrix = *matrix;
7597         layer->color[0] = r;
7598         layer->color[1] = g;
7599         layer->color[2] = b;
7600         layer->color[3] = a;
7601 }
7602
7603 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7604 {
7605         if(parms[0] == 0 && parms[1] == 0)
7606                 return false;
7607         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7608                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7609                         return false;
7610         return true;
7611 }
7612
7613 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7614 {
7615         double index, f;
7616         index = parms[2] + rsurface.shadertime * parms[3];
7617         index -= floor(index);
7618         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7619         {
7620         default:
7621         case Q3WAVEFUNC_NONE:
7622         case Q3WAVEFUNC_NOISE:
7623         case Q3WAVEFUNC_COUNT:
7624                 f = 0;
7625                 break;
7626         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7627         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7628         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7629         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7630         case Q3WAVEFUNC_TRIANGLE:
7631                 index *= 4;
7632                 f = index - floor(index);
7633                 if (index < 1)
7634                 {
7635                         // f = f;
7636                 }
7637                 else if (index < 2)
7638                         f = 1 - f;
7639                 else if (index < 3)
7640                         f = -f;
7641                 else
7642                         f = -(1 - f);
7643                 break;
7644         }
7645         f = parms[0] + parms[1] * f;
7646         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7647                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7648         return (float) f;
7649 }
7650
7651 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7652 {
7653         int w, h, idx;
7654         double f;
7655         double offsetd[2];
7656         float tcmat[12];
7657         matrix4x4_t matrix, temp;
7658         switch(tcmod->tcmod)
7659         {
7660                 case Q3TCMOD_COUNT:
7661                 case Q3TCMOD_NONE:
7662                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7663                                 matrix = r_waterscrollmatrix;
7664                         else
7665                                 matrix = identitymatrix;
7666                         break;
7667                 case Q3TCMOD_ENTITYTRANSLATE:
7668                         // this is used in Q3 to allow the gamecode to control texcoord
7669                         // scrolling on the entity, which is not supported in darkplaces yet.
7670                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7671                         break;
7672                 case Q3TCMOD_ROTATE:
7673                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7674                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7675                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7676                         break;
7677                 case Q3TCMOD_SCALE:
7678                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7679                         break;
7680                 case Q3TCMOD_SCROLL:
7681                         // extra care is needed because of precision breakdown with large values of time
7682                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7683                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7684                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7685                         break;
7686                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7687                         w = (int) tcmod->parms[0];
7688                         h = (int) tcmod->parms[1];
7689                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7690                         f = f - floor(f);
7691                         idx = (int) floor(f * w * h);
7692                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7693                         break;
7694                 case Q3TCMOD_STRETCH:
7695                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7696                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7697                         break;
7698                 case Q3TCMOD_TRANSFORM:
7699                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7700                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7701                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7702                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7703                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7704                         break;
7705                 case Q3TCMOD_TURBULENT:
7706                         // this is handled in the RSurf_PrepareVertices function
7707                         matrix = identitymatrix;
7708                         break;
7709         }
7710         temp = *texmatrix;
7711         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7712 }
7713
7714 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7715 {
7716         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7717         char name[MAX_QPATH];
7718         skinframe_t *skinframe;
7719         unsigned char pixels[296*194];
7720         strlcpy(cache->name, skinname, sizeof(cache->name));
7721         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7722         if (developer_loading.integer)
7723                 Con_Printf("loading %s\n", name);
7724         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7725         if (!skinframe || !skinframe->base)
7726         {
7727                 unsigned char *f;
7728                 fs_offset_t filesize;
7729                 skinframe = NULL;
7730                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7731                 if (f)
7732                 {
7733                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7734                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7735                         Mem_Free(f);
7736                 }
7737         }
7738         cache->skinframe = skinframe;
7739 }
7740
7741 texture_t *R_GetCurrentTexture(texture_t *t)
7742 {
7743         int i;
7744         const entity_render_t *ent = rsurface.entity;
7745         dp_model_t *model = ent->model;
7746         q3shaderinfo_layer_tcmod_t *tcmod;
7747
7748         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7749                 return t->currentframe;
7750         t->update_lastrenderframe = r_textureframe;
7751         t->update_lastrenderentity = (void *)ent;
7752
7753         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7754                 t->camera_entity = ent->entitynumber;
7755         else
7756                 t->camera_entity = 0;
7757
7758         // switch to an alternate material if this is a q1bsp animated material
7759         {
7760                 texture_t *texture = t;
7761                 int s = rsurface.ent_skinnum;
7762                 if ((unsigned int)s >= (unsigned int)model->numskins)
7763                         s = 0;
7764                 if (model->skinscenes)
7765                 {
7766                         if (model->skinscenes[s].framecount > 1)
7767                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7768                         else
7769                                 s = model->skinscenes[s].firstframe;
7770                 }
7771                 if (s > 0)
7772                         t = t + s * model->num_surfaces;
7773                 if (t->animated)
7774                 {
7775                         // use an alternate animation if the entity's frame is not 0,
7776                         // and only if the texture has an alternate animation
7777                         if (rsurface.ent_alttextures && t->anim_total[1])
7778                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7779                         else
7780                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7781                 }
7782                 texture->currentframe = t;
7783         }
7784
7785         // update currentskinframe to be a qw skin or animation frame
7786         if (rsurface.ent_qwskin >= 0)
7787         {
7788                 i = rsurface.ent_qwskin;
7789                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7790                 {
7791                         r_qwskincache_size = cl.maxclients;
7792                         if (r_qwskincache)
7793                                 Mem_Free(r_qwskincache);
7794                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7795                 }
7796                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7797                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7798                 t->currentskinframe = r_qwskincache[i].skinframe;
7799                 if (t->currentskinframe == NULL)
7800                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7801         }
7802         else if (t->numskinframes >= 2)
7803                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7804         if (t->backgroundnumskinframes >= 2)
7805                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7806
7807         t->currentmaterialflags = t->basematerialflags;
7808         t->currentalpha = rsurface.colormod[3];
7809         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7810                 t->currentalpha *= r_wateralpha.value;
7811         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7812                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7813         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7814                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7815         if (!(rsurface.ent_flags & RENDER_LIGHT))
7816                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7817         else if (FAKELIGHT_ENABLED)
7818         {
7819                 // no modellight if using fakelight for the map
7820         }
7821         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7822         {
7823                 // pick a model lighting mode
7824                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7825                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7826                 else
7827                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7828         }
7829         if (rsurface.ent_flags & RENDER_ADDITIVE)
7830                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7831         else if (t->currentalpha < 1)
7832                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7833         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7834                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7835         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7836                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7837         if (t->backgroundnumskinframes)
7838                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7839         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7840         {
7841                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7842                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7843         }
7844         else
7845                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7846         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7847         {
7848                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7849                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7850         }
7851         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7852                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7853
7854         // there is no tcmod
7855         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7856         {
7857                 t->currenttexmatrix = r_waterscrollmatrix;
7858                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7859         }
7860         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7861         {
7862                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7863                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7864         }
7865
7866         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7867                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7868         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7869                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7870
7871         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7872         if (t->currentskinframe->qpixels)
7873                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7874         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7875         if (!t->basetexture)
7876                 t->basetexture = r_texture_notexture;
7877         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7878         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7879         t->nmaptexture = t->currentskinframe->nmap;
7880         if (!t->nmaptexture)
7881                 t->nmaptexture = r_texture_blanknormalmap;
7882         t->glosstexture = r_texture_black;
7883         t->glowtexture = t->currentskinframe->glow;
7884         t->fogtexture = t->currentskinframe->fog;
7885         t->reflectmasktexture = t->currentskinframe->reflect;
7886         if (t->backgroundnumskinframes)
7887         {
7888                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7889                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7890                 t->backgroundglosstexture = r_texture_black;
7891                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7892                 if (!t->backgroundnmaptexture)
7893                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7894         }
7895         else
7896         {
7897                 t->backgroundbasetexture = r_texture_white;
7898                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7899                 t->backgroundglosstexture = r_texture_black;
7900                 t->backgroundglowtexture = NULL;
7901         }
7902         t->specularpower = r_shadow_glossexponent.value;
7903         // TODO: store reference values for these in the texture?
7904         t->specularscale = 0;
7905         if (r_shadow_gloss.integer > 0)
7906         {
7907                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7908                 {
7909                         if (r_shadow_glossintensity.value > 0)
7910                         {
7911                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7912                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7913                                 t->specularscale = r_shadow_glossintensity.value;
7914                         }
7915                 }
7916                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7917                 {
7918                         t->glosstexture = r_texture_white;
7919                         t->backgroundglosstexture = r_texture_white;
7920                         t->specularscale = r_shadow_gloss2intensity.value;
7921                         t->specularpower = r_shadow_gloss2exponent.value;
7922                 }
7923         }
7924         t->specularscale *= t->specularscalemod;
7925         t->specularpower *= t->specularpowermod;
7926         t->rtlightambient = 0;
7927
7928         // lightmaps mode looks bad with dlights using actual texturing, so turn
7929         // off the colormap and glossmap, but leave the normalmap on as it still
7930         // accurately represents the shading involved
7931         if (gl_lightmaps.integer)
7932         {
7933                 t->basetexture = r_texture_grey128;
7934                 t->pantstexture = r_texture_black;
7935                 t->shirttexture = r_texture_black;
7936                 t->nmaptexture = r_texture_blanknormalmap;
7937                 t->glosstexture = r_texture_black;
7938                 t->glowtexture = NULL;
7939                 t->fogtexture = NULL;
7940                 t->reflectmasktexture = NULL;
7941                 t->backgroundbasetexture = NULL;
7942                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7943                 t->backgroundglosstexture = r_texture_black;
7944                 t->backgroundglowtexture = NULL;
7945                 t->specularscale = 0;
7946                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7947         }
7948
7949         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7950         VectorClear(t->dlightcolor);
7951         t->currentnumlayers = 0;
7952         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7953         {
7954                 int blendfunc1, blendfunc2;
7955                 qboolean depthmask;
7956                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7957                 {
7958                         blendfunc1 = GL_SRC_ALPHA;
7959                         blendfunc2 = GL_ONE;
7960                 }
7961                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7962                 {
7963                         blendfunc1 = GL_SRC_ALPHA;
7964                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7965                 }
7966                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7967                 {
7968                         blendfunc1 = t->customblendfunc[0];
7969                         blendfunc2 = t->customblendfunc[1];
7970                 }
7971                 else
7972                 {
7973                         blendfunc1 = GL_ONE;
7974                         blendfunc2 = GL_ZERO;
7975                 }
7976                 // don't colormod evilblend textures
7977                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7978                         VectorSet(t->lightmapcolor, 1, 1, 1);
7979                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7980                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7981                 {
7982                         // fullbright is not affected by r_refdef.lightmapintensity
7983                         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]);
7984                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7985                                 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]);
7986                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7987                                 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]);
7988                 }
7989                 else
7990                 {
7991                         vec3_t ambientcolor;
7992                         float colorscale;
7993                         // set the color tint used for lights affecting this surface
7994                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7995                         colorscale = 2;
7996                         // q3bsp has no lightmap updates, so the lightstylevalue that
7997                         // would normally be baked into the lightmap must be
7998                         // applied to the color
7999                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8000                         if (model->type == mod_brushq3)
8001                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8002                         colorscale *= r_refdef.lightmapintensity;
8003                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8004                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8005                         // basic lit geometry
8006                         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]);
8007                         // add pants/shirt if needed
8008                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8009                                 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]);
8010                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8011                                 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]);
8012                         // now add ambient passes if needed
8013                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8014                         {
8015                                 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]);
8016                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8017                                         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]);
8018                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8019                                         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]);
8020                         }
8021                 }
8022                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8023                         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]);
8024                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8025                 {
8026                         // if this is opaque use alpha blend which will darken the earlier
8027                         // passes cheaply.
8028                         //
8029                         // if this is an alpha blended material, all the earlier passes
8030                         // were darkened by fog already, so we only need to add the fog
8031                         // color ontop through the fog mask texture
8032                         //
8033                         // if this is an additive blended material, all the earlier passes
8034                         // were darkened by fog already, and we should not add fog color
8035                         // (because the background was not darkened, there is no fog color
8036                         // that was lost behind it).
8037                         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]);
8038                 }
8039         }
8040
8041         return t->currentframe;
8042 }
8043
8044 rsurfacestate_t rsurface;
8045
8046 void RSurf_ActiveWorldEntity(void)
8047 {
8048         dp_model_t *model = r_refdef.scene.worldmodel;
8049         //if (rsurface.entity == r_refdef.scene.worldentity)
8050         //      return;
8051         rsurface.entity = r_refdef.scene.worldentity;
8052         rsurface.skeleton = NULL;
8053         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8054         rsurface.ent_skinnum = 0;
8055         rsurface.ent_qwskin = -1;
8056         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8057         rsurface.shadertime = r_refdef.scene.time;
8058         rsurface.matrix = identitymatrix;
8059         rsurface.inversematrix = identitymatrix;
8060         rsurface.matrixscale = 1;
8061         rsurface.inversematrixscale = 1;
8062         R_EntityMatrix(&identitymatrix);
8063         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8064         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8065         rsurface.fograngerecip = r_refdef.fograngerecip;
8066         rsurface.fogheightfade = r_refdef.fogheightfade;
8067         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8068         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8069         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8070         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8071         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8072         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8073         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8074         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8075         rsurface.colormod[3] = 1;
8076         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);
8077         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8078         rsurface.frameblend[0].lerp = 1;
8079         rsurface.ent_alttextures = false;
8080         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8081         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8082         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8083         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8084         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8085         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8086         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8087         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8088         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8089         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8090         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8091         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8092         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8093         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8094         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8095         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8096         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8097         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8098         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8099         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8100         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8101         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8102         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8103         rsurface.modelelement3i = model->surfmesh.data_element3i;
8104         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8105         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8106         rsurface.modelelement3s = model->surfmesh.data_element3s;
8107         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8108         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8109         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8110         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8111         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8112         rsurface.modelsurfaces = model->data_surfaces;
8113         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8114         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8115         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8116         rsurface.modelgeneratedvertex = false;
8117         rsurface.batchgeneratedvertex = false;
8118         rsurface.batchfirstvertex = 0;
8119         rsurface.batchnumvertices = 0;
8120         rsurface.batchfirsttriangle = 0;
8121         rsurface.batchnumtriangles = 0;
8122         rsurface.batchvertex3f  = NULL;
8123         rsurface.batchvertex3f_vertexbuffer = NULL;
8124         rsurface.batchvertex3f_bufferoffset = 0;
8125         rsurface.batchsvector3f = NULL;
8126         rsurface.batchsvector3f_vertexbuffer = NULL;
8127         rsurface.batchsvector3f_bufferoffset = 0;
8128         rsurface.batchtvector3f = NULL;
8129         rsurface.batchtvector3f_vertexbuffer = NULL;
8130         rsurface.batchtvector3f_bufferoffset = 0;
8131         rsurface.batchnormal3f  = NULL;
8132         rsurface.batchnormal3f_vertexbuffer = NULL;
8133         rsurface.batchnormal3f_bufferoffset = 0;
8134         rsurface.batchlightmapcolor4f = NULL;
8135         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8136         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8137         rsurface.batchtexcoordtexture2f = NULL;
8138         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8139         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8140         rsurface.batchtexcoordlightmap2f = NULL;
8141         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8142         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8143         rsurface.batchvertexmesh = NULL;
8144         rsurface.batchvertexmeshbuffer = NULL;
8145         rsurface.batchvertex3fbuffer = NULL;
8146         rsurface.batchelement3i = NULL;
8147         rsurface.batchelement3i_indexbuffer = NULL;
8148         rsurface.batchelement3i_bufferoffset = 0;
8149         rsurface.batchelement3s = NULL;
8150         rsurface.batchelement3s_indexbuffer = NULL;
8151         rsurface.batchelement3s_bufferoffset = 0;
8152         rsurface.passcolor4f = NULL;
8153         rsurface.passcolor4f_vertexbuffer = NULL;
8154         rsurface.passcolor4f_bufferoffset = 0;
8155 }
8156
8157 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8158 {
8159         dp_model_t *model = ent->model;
8160         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8161         //      return;
8162         rsurface.entity = (entity_render_t *)ent;
8163         rsurface.skeleton = ent->skeleton;
8164         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8165         rsurface.ent_skinnum = ent->skinnum;
8166         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;
8167         rsurface.ent_flags = ent->flags;
8168         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8169         rsurface.matrix = ent->matrix;
8170         rsurface.inversematrix = ent->inversematrix;
8171         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8172         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8173         R_EntityMatrix(&rsurface.matrix);
8174         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8175         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8176         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8177         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8178         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8179         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8180         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8181         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8182         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8183         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8184         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8185         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8186         rsurface.colormod[3] = ent->alpha;
8187         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8188         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8189         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8190         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8191         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8192         if (ent->model->brush.submodel && !prepass)
8193         {
8194                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8195                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8196         }
8197         if (model->surfmesh.isanimated && model->AnimateVertices)
8198         {
8199                 if (ent->animcache_vertex3f)
8200                 {
8201                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8202                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8203                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8204                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8205                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8206                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8207                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8208                 }
8209                 else if (wanttangents)
8210                 {
8211                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8212                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8213                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8214                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8215                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8216                         rsurface.modelvertexmesh = NULL;
8217                         rsurface.modelvertexmeshbuffer = NULL;
8218                         rsurface.modelvertex3fbuffer = NULL;
8219                 }
8220                 else if (wantnormals)
8221                 {
8222                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8223                         rsurface.modelsvector3f = NULL;
8224                         rsurface.modeltvector3f = NULL;
8225                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8226                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8227                         rsurface.modelvertexmesh = NULL;
8228                         rsurface.modelvertexmeshbuffer = NULL;
8229                         rsurface.modelvertex3fbuffer = NULL;
8230                 }
8231                 else
8232                 {
8233                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8234                         rsurface.modelsvector3f = NULL;
8235                         rsurface.modeltvector3f = NULL;
8236                         rsurface.modelnormal3f = NULL;
8237                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8238                         rsurface.modelvertexmesh = NULL;
8239                         rsurface.modelvertexmeshbuffer = NULL;
8240                         rsurface.modelvertex3fbuffer = NULL;
8241                 }
8242                 rsurface.modelvertex3f_vertexbuffer = 0;
8243                 rsurface.modelvertex3f_bufferoffset = 0;
8244                 rsurface.modelsvector3f_vertexbuffer = 0;
8245                 rsurface.modelsvector3f_bufferoffset = 0;
8246                 rsurface.modeltvector3f_vertexbuffer = 0;
8247                 rsurface.modeltvector3f_bufferoffset = 0;
8248                 rsurface.modelnormal3f_vertexbuffer = 0;
8249                 rsurface.modelnormal3f_bufferoffset = 0;
8250                 rsurface.modelgeneratedvertex = true;
8251         }
8252         else
8253         {
8254                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8255                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8256                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8257                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8258                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8259                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8260                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8261                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8262                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8263                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8264                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8265                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8266                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8267                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8268                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8269                 rsurface.modelgeneratedvertex = false;
8270         }
8271         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8272         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8273         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8274         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8275         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8276         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8277         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8278         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8279         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8280         rsurface.modelelement3i = model->surfmesh.data_element3i;
8281         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8282         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8283         rsurface.modelelement3s = model->surfmesh.data_element3s;
8284         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8285         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8286         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8287         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8288         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8289         rsurface.modelsurfaces = model->data_surfaces;
8290         rsurface.batchgeneratedvertex = false;
8291         rsurface.batchfirstvertex = 0;
8292         rsurface.batchnumvertices = 0;
8293         rsurface.batchfirsttriangle = 0;
8294         rsurface.batchnumtriangles = 0;
8295         rsurface.batchvertex3f  = NULL;
8296         rsurface.batchvertex3f_vertexbuffer = NULL;
8297         rsurface.batchvertex3f_bufferoffset = 0;
8298         rsurface.batchsvector3f = NULL;
8299         rsurface.batchsvector3f_vertexbuffer = NULL;
8300         rsurface.batchsvector3f_bufferoffset = 0;
8301         rsurface.batchtvector3f = NULL;
8302         rsurface.batchtvector3f_vertexbuffer = NULL;
8303         rsurface.batchtvector3f_bufferoffset = 0;
8304         rsurface.batchnormal3f  = NULL;
8305         rsurface.batchnormal3f_vertexbuffer = NULL;
8306         rsurface.batchnormal3f_bufferoffset = 0;
8307         rsurface.batchlightmapcolor4f = NULL;
8308         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8309         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8310         rsurface.batchtexcoordtexture2f = NULL;
8311         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8312         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8313         rsurface.batchtexcoordlightmap2f = NULL;
8314         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8315         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8316         rsurface.batchvertexmesh = NULL;
8317         rsurface.batchvertexmeshbuffer = NULL;
8318         rsurface.batchvertex3fbuffer = NULL;
8319         rsurface.batchelement3i = NULL;
8320         rsurface.batchelement3i_indexbuffer = NULL;
8321         rsurface.batchelement3i_bufferoffset = 0;
8322         rsurface.batchelement3s = NULL;
8323         rsurface.batchelement3s_indexbuffer = NULL;
8324         rsurface.batchelement3s_bufferoffset = 0;
8325         rsurface.passcolor4f = NULL;
8326         rsurface.passcolor4f_vertexbuffer = NULL;
8327         rsurface.passcolor4f_bufferoffset = 0;
8328 }
8329
8330 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)
8331 {
8332         rsurface.entity = r_refdef.scene.worldentity;
8333         rsurface.skeleton = NULL;
8334         rsurface.ent_skinnum = 0;
8335         rsurface.ent_qwskin = -1;
8336         rsurface.ent_flags = entflags;
8337         rsurface.shadertime = r_refdef.scene.time - shadertime;
8338         rsurface.modelnumvertices = numvertices;
8339         rsurface.modelnumtriangles = numtriangles;
8340         rsurface.matrix = *matrix;
8341         rsurface.inversematrix = *inversematrix;
8342         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8343         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8344         R_EntityMatrix(&rsurface.matrix);
8345         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8346         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8347         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8348         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8349         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8350         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8351         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8352         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8353         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8354         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8355         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8356         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8357         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);
8358         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8359         rsurface.frameblend[0].lerp = 1;
8360         rsurface.ent_alttextures = false;
8361         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8362         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8363         if (wanttangents)
8364         {
8365                 rsurface.modelvertex3f = (float *)vertex3f;
8366                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8367                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8368                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8369         }
8370         else if (wantnormals)
8371         {
8372                 rsurface.modelvertex3f = (float *)vertex3f;
8373                 rsurface.modelsvector3f = NULL;
8374                 rsurface.modeltvector3f = NULL;
8375                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8376         }
8377         else
8378         {
8379                 rsurface.modelvertex3f = (float *)vertex3f;
8380                 rsurface.modelsvector3f = NULL;
8381                 rsurface.modeltvector3f = NULL;
8382                 rsurface.modelnormal3f = NULL;
8383         }
8384         rsurface.modelvertexmesh = NULL;
8385         rsurface.modelvertexmeshbuffer = NULL;
8386         rsurface.modelvertex3fbuffer = NULL;
8387         rsurface.modelvertex3f_vertexbuffer = 0;
8388         rsurface.modelvertex3f_bufferoffset = 0;
8389         rsurface.modelsvector3f_vertexbuffer = 0;
8390         rsurface.modelsvector3f_bufferoffset = 0;
8391         rsurface.modeltvector3f_vertexbuffer = 0;
8392         rsurface.modeltvector3f_bufferoffset = 0;
8393         rsurface.modelnormal3f_vertexbuffer = 0;
8394         rsurface.modelnormal3f_bufferoffset = 0;
8395         rsurface.modelgeneratedvertex = true;
8396         rsurface.modellightmapcolor4f  = (float *)color4f;
8397         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8398         rsurface.modellightmapcolor4f_bufferoffset = 0;
8399         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8400         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8401         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8402         rsurface.modeltexcoordlightmap2f  = NULL;
8403         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8404         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8405         rsurface.modelelement3i = (int *)element3i;
8406         rsurface.modelelement3i_indexbuffer = NULL;
8407         rsurface.modelelement3i_bufferoffset = 0;
8408         rsurface.modelelement3s = (unsigned short *)element3s;
8409         rsurface.modelelement3s_indexbuffer = NULL;
8410         rsurface.modelelement3s_bufferoffset = 0;
8411         rsurface.modellightmapoffsets = NULL;
8412         rsurface.modelsurfaces = NULL;
8413         rsurface.batchgeneratedvertex = false;
8414         rsurface.batchfirstvertex = 0;
8415         rsurface.batchnumvertices = 0;
8416         rsurface.batchfirsttriangle = 0;
8417         rsurface.batchnumtriangles = 0;
8418         rsurface.batchvertex3f  = NULL;
8419         rsurface.batchvertex3f_vertexbuffer = NULL;
8420         rsurface.batchvertex3f_bufferoffset = 0;
8421         rsurface.batchsvector3f = NULL;
8422         rsurface.batchsvector3f_vertexbuffer = NULL;
8423         rsurface.batchsvector3f_bufferoffset = 0;
8424         rsurface.batchtvector3f = NULL;
8425         rsurface.batchtvector3f_vertexbuffer = NULL;
8426         rsurface.batchtvector3f_bufferoffset = 0;
8427         rsurface.batchnormal3f  = NULL;
8428         rsurface.batchnormal3f_vertexbuffer = NULL;
8429         rsurface.batchnormal3f_bufferoffset = 0;
8430         rsurface.batchlightmapcolor4f = NULL;
8431         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8432         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8433         rsurface.batchtexcoordtexture2f = NULL;
8434         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8435         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8436         rsurface.batchtexcoordlightmap2f = NULL;
8437         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8438         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8439         rsurface.batchvertexmesh = NULL;
8440         rsurface.batchvertexmeshbuffer = NULL;
8441         rsurface.batchvertex3fbuffer = NULL;
8442         rsurface.batchelement3i = NULL;
8443         rsurface.batchelement3i_indexbuffer = NULL;
8444         rsurface.batchelement3i_bufferoffset = 0;
8445         rsurface.batchelement3s = NULL;
8446         rsurface.batchelement3s_indexbuffer = NULL;
8447         rsurface.batchelement3s_bufferoffset = 0;
8448         rsurface.passcolor4f = NULL;
8449         rsurface.passcolor4f_vertexbuffer = NULL;
8450         rsurface.passcolor4f_bufferoffset = 0;
8451
8452         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8453         {
8454                 if ((wantnormals || wanttangents) && !normal3f)
8455                 {
8456                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8457                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8458                 }
8459                 if (wanttangents && !svector3f)
8460                 {
8461                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8462                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8463                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8464                 }
8465         }
8466 }
8467
8468 float RSurf_FogPoint(const float *v)
8469 {
8470         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8471         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8472         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8473         float FogHeightFade = r_refdef.fogheightfade;
8474         float fogfrac;
8475         unsigned int fogmasktableindex;
8476         if (r_refdef.fogplaneviewabove)
8477                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8478         else
8479                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8480         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8481         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8482 }
8483
8484 float RSurf_FogVertex(const float *v)
8485 {
8486         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8487         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8488         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8489         float FogHeightFade = rsurface.fogheightfade;
8490         float fogfrac;
8491         unsigned int fogmasktableindex;
8492         if (r_refdef.fogplaneviewabove)
8493                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8494         else
8495                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8496         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8497         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8498 }
8499
8500 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8501 {
8502         int i;
8503         for (i = 0;i < numelements;i++)
8504                 outelement3i[i] = inelement3i[i] + adjust;
8505 }
8506
8507 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8508 extern cvar_t gl_vbo;
8509 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8510 {
8511         int deformindex;
8512         int firsttriangle;
8513         int numtriangles;
8514         int firstvertex;
8515         int endvertex;
8516         int numvertices;
8517         int surfacefirsttriangle;
8518         int surfacenumtriangles;
8519         int surfacefirstvertex;
8520         int surfaceendvertex;
8521         int surfacenumvertices;
8522         int batchnumvertices;
8523         int batchnumtriangles;
8524         int needsupdate;
8525         int i, j;
8526         qboolean gaps;
8527         qboolean dynamicvertex;
8528         float amplitude;
8529         float animpos;
8530         float scale;
8531         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8532         float waveparms[4];
8533         q3shaderinfo_deform_t *deform;
8534         const msurface_t *surface, *firstsurface;
8535         r_vertexmesh_t *vertexmesh;
8536         if (!texturenumsurfaces)
8537                 return;
8538         // find vertex range of this surface batch
8539         gaps = false;
8540         firstsurface = texturesurfacelist[0];
8541         firsttriangle = firstsurface->num_firsttriangle;
8542         batchnumvertices = 0;
8543         batchnumtriangles = 0;
8544         firstvertex = endvertex = firstsurface->num_firstvertex;
8545         for (i = 0;i < texturenumsurfaces;i++)
8546         {
8547                 surface = texturesurfacelist[i];
8548                 if (surface != firstsurface + i)
8549                         gaps = true;
8550                 surfacefirstvertex = surface->num_firstvertex;
8551                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8552                 surfacenumvertices = surface->num_vertices;
8553                 surfacenumtriangles = surface->num_triangles;
8554                 if (firstvertex > surfacefirstvertex)
8555                         firstvertex = surfacefirstvertex;
8556                 if (endvertex < surfaceendvertex)
8557                         endvertex = surfaceendvertex;
8558                 batchnumvertices += surfacenumvertices;
8559                 batchnumtriangles += surfacenumtriangles;
8560         }
8561
8562         // we now know the vertex range used, and if there are any gaps in it
8563         rsurface.batchfirstvertex = firstvertex;
8564         rsurface.batchnumvertices = endvertex - firstvertex;
8565         rsurface.batchfirsttriangle = firsttriangle;
8566         rsurface.batchnumtriangles = batchnumtriangles;
8567
8568         // this variable holds flags for which properties have been updated that
8569         // may require regenerating vertexmesh array...
8570         needsupdate = 0;
8571
8572         // check if any dynamic vertex processing must occur
8573         dynamicvertex = false;
8574
8575         // if there is a chance of animated vertex colors, it's a dynamic batch
8576         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8577         {
8578                 dynamicvertex = true;
8579                 batchneed |= BATCHNEED_NOGAPS;
8580                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8581         }
8582
8583         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8584         {
8585                 switch (deform->deform)
8586                 {
8587                 default:
8588                 case Q3DEFORM_PROJECTIONSHADOW:
8589                 case Q3DEFORM_TEXT0:
8590                 case Q3DEFORM_TEXT1:
8591                 case Q3DEFORM_TEXT2:
8592                 case Q3DEFORM_TEXT3:
8593                 case Q3DEFORM_TEXT4:
8594                 case Q3DEFORM_TEXT5:
8595                 case Q3DEFORM_TEXT6:
8596                 case Q3DEFORM_TEXT7:
8597                 case Q3DEFORM_NONE:
8598                         break;
8599                 case Q3DEFORM_AUTOSPRITE:
8600                         dynamicvertex = true;
8601                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8602                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8603                         break;
8604                 case Q3DEFORM_AUTOSPRITE2:
8605                         dynamicvertex = true;
8606                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8607                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8608                         break;
8609                 case Q3DEFORM_NORMAL:
8610                         dynamicvertex = true;
8611                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8612                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8613                         break;
8614                 case Q3DEFORM_WAVE:
8615                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8616                                 break; // if wavefunc is a nop, ignore this transform
8617                         dynamicvertex = true;
8618                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8619                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8620                         break;
8621                 case Q3DEFORM_BULGE:
8622                         dynamicvertex = true;
8623                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8624                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8625                         break;
8626                 case Q3DEFORM_MOVE:
8627                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8628                                 break; // if wavefunc is a nop, ignore this transform
8629                         dynamicvertex = true;
8630                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8631                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8632                         break;
8633                 }
8634         }
8635         switch(rsurface.texture->tcgen.tcgen)
8636         {
8637         default:
8638         case Q3TCGEN_TEXTURE:
8639                 break;
8640         case Q3TCGEN_LIGHTMAP:
8641                 dynamicvertex = true;
8642                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8643                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8644                 break;
8645         case Q3TCGEN_VECTOR:
8646                 dynamicvertex = true;
8647                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8648                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8649                 break;
8650         case Q3TCGEN_ENVIRONMENT:
8651                 dynamicvertex = true;
8652                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8653                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8654                 break;
8655         }
8656         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8657         {
8658                 dynamicvertex = true;
8659                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8660                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8661         }
8662
8663         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8664         {
8665                 dynamicvertex = true;
8666                 batchneed |= BATCHNEED_NOGAPS;
8667                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8668         }
8669
8670         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8671         {
8672                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8673                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8674                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8675                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8676                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8677                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8678                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8679         }
8680
8681         // when the model data has no vertex buffer (dynamic mesh), we need to
8682         // eliminate gaps
8683         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8684                 batchneed |= BATCHNEED_NOGAPS;
8685
8686         // if needsupdate, we have to do a dynamic vertex batch for sure
8687         if (needsupdate & batchneed)
8688                 dynamicvertex = true;
8689
8690         // see if we need to build vertexmesh from arrays
8691         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8692                 dynamicvertex = true;
8693
8694         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8695         // also some drivers strongly dislike firstvertex
8696         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8697                 dynamicvertex = true;
8698
8699         rsurface.batchvertex3f = rsurface.modelvertex3f;
8700         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8701         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8702         rsurface.batchsvector3f = rsurface.modelsvector3f;
8703         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8704         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8705         rsurface.batchtvector3f = rsurface.modeltvector3f;
8706         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8707         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8708         rsurface.batchnormal3f = rsurface.modelnormal3f;
8709         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8710         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8711         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8712         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8713         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8714         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8715         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8716         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8717         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8718         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8719         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8720         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8721         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8722         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8723         rsurface.batchelement3i = rsurface.modelelement3i;
8724         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8725         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8726         rsurface.batchelement3s = rsurface.modelelement3s;
8727         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8728         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8729
8730         // if any dynamic vertex processing has to occur in software, we copy the
8731         // entire surface list together before processing to rebase the vertices
8732         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8733         //
8734         // if any gaps exist and we do not have a static vertex buffer, we have to
8735         // copy the surface list together to avoid wasting upload bandwidth on the
8736         // vertices in the gaps.
8737         //
8738         // if gaps exist and we have a static vertex buffer, we still have to
8739         // combine the index buffer ranges into one dynamic index buffer.
8740         //
8741         // in all cases we end up with data that can be drawn in one call.
8742
8743         if (!dynamicvertex)
8744         {
8745                 // static vertex data, just set pointers...
8746                 rsurface.batchgeneratedvertex = false;
8747                 // if there are gaps, we want to build a combined index buffer,
8748                 // otherwise use the original static buffer with an appropriate offset
8749                 if (gaps)
8750                 {
8751                         // build a new triangle elements array for this batch
8752                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8753                         rsurface.batchfirsttriangle = 0;
8754                         numtriangles = 0;
8755                         for (i = 0;i < texturenumsurfaces;i++)
8756                         {
8757                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8758                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8759                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8760                                 numtriangles += surfacenumtriangles;
8761                         }
8762                         rsurface.batchelement3i_indexbuffer = NULL;
8763                         rsurface.batchelement3i_bufferoffset = 0;
8764                         rsurface.batchelement3s = NULL;
8765                         rsurface.batchelement3s_indexbuffer = NULL;
8766                         rsurface.batchelement3s_bufferoffset = 0;
8767                         if (endvertex <= 65536)
8768                         {
8769                                 // make a 16bit (unsigned short) index array if possible
8770                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8771                                 for (i = 0;i < numtriangles*3;i++)
8772                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8773                         }
8774                 }
8775                 return;
8776         }
8777
8778         // something needs software processing, do it for real...
8779         // we only directly handle separate array data in this case and then
8780         // generate interleaved data if needed...
8781         rsurface.batchgeneratedvertex = true;
8782
8783         // now copy the vertex data into a combined array and make an index array
8784         // (this is what Quake3 does all the time)
8785         //if (gaps || rsurface.batchfirstvertex)
8786         {
8787                 rsurface.batchvertex3fbuffer = NULL;
8788                 rsurface.batchvertexmesh = NULL;
8789                 rsurface.batchvertexmeshbuffer = NULL;
8790                 rsurface.batchvertex3f = NULL;
8791                 rsurface.batchvertex3f_vertexbuffer = NULL;
8792                 rsurface.batchvertex3f_bufferoffset = 0;
8793                 rsurface.batchsvector3f = NULL;
8794                 rsurface.batchsvector3f_vertexbuffer = NULL;
8795                 rsurface.batchsvector3f_bufferoffset = 0;
8796                 rsurface.batchtvector3f = NULL;
8797                 rsurface.batchtvector3f_vertexbuffer = NULL;
8798                 rsurface.batchtvector3f_bufferoffset = 0;
8799                 rsurface.batchnormal3f = NULL;
8800                 rsurface.batchnormal3f_vertexbuffer = NULL;
8801                 rsurface.batchnormal3f_bufferoffset = 0;
8802                 rsurface.batchlightmapcolor4f = NULL;
8803                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8804                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8805                 rsurface.batchtexcoordtexture2f = NULL;
8806                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8807                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8808                 rsurface.batchtexcoordlightmap2f = NULL;
8809                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8810                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8811                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8812                 rsurface.batchelement3i_indexbuffer = NULL;
8813                 rsurface.batchelement3i_bufferoffset = 0;
8814                 rsurface.batchelement3s = NULL;
8815                 rsurface.batchelement3s_indexbuffer = NULL;
8816                 rsurface.batchelement3s_bufferoffset = 0;
8817                 // we'll only be setting up certain arrays as needed
8818                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8819                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8820                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8821                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8822                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8823                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8824                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8825                 {
8826                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8827                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8828                 }
8829                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8830                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8831                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8832                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8833                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8834                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8835                 numvertices = 0;
8836                 numtriangles = 0;
8837                 for (i = 0;i < texturenumsurfaces;i++)
8838                 {
8839                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8840                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8841                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8842                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8843                         // copy only the data requested
8844                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8845                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8846                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8847                         {
8848                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8849                                 {
8850                                         if (rsurface.batchvertex3f)
8851                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8852                                         else
8853                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8854                                 }
8855                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8856                                 {
8857                                         if (rsurface.modelnormal3f)
8858                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8859                                         else
8860                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8861                                 }
8862                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8863                                 {
8864                                         if (rsurface.modelsvector3f)
8865                                         {
8866                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8867                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8868                                         }
8869                                         else
8870                                         {
8871                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8872                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8873                                         }
8874                                 }
8875                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8876                                 {
8877                                         if (rsurface.modellightmapcolor4f)
8878                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8879                                         else
8880                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8881                                 }
8882                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8883                                 {
8884                                         if (rsurface.modeltexcoordtexture2f)
8885                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8886                                         else
8887                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8888                                 }
8889                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8890                                 {
8891                                         if (rsurface.modeltexcoordlightmap2f)
8892                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8893                                         else
8894                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8895                                 }
8896                         }
8897                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8898                         numvertices += surfacenumvertices;
8899                         numtriangles += surfacenumtriangles;
8900                 }
8901
8902                 // generate a 16bit index array as well if possible
8903                 // (in general, dynamic batches fit)
8904                 if (numvertices <= 65536)
8905                 {
8906                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8907                         for (i = 0;i < numtriangles*3;i++)
8908                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8909                 }
8910
8911                 // since we've copied everything, the batch now starts at 0
8912                 rsurface.batchfirstvertex = 0;
8913                 rsurface.batchnumvertices = batchnumvertices;
8914                 rsurface.batchfirsttriangle = 0;
8915                 rsurface.batchnumtriangles = batchnumtriangles;
8916         }
8917
8918         // q1bsp surfaces rendered in vertex color mode have to have colors
8919         // calculated based on lightstyles
8920         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8921         {
8922                 // generate color arrays for the surfaces in this list
8923                 int c[4];
8924                 int scale;
8925                 int size3;
8926                 const int *offsets;
8927                 const unsigned char *lm;
8928                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8929                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8930                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8931                 numvertices = 0;
8932                 for (i = 0;i < texturenumsurfaces;i++)
8933                 {
8934                         surface = texturesurfacelist[i];
8935                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8936                         surfacenumvertices = surface->num_vertices;
8937                         if (surface->lightmapinfo->samples)
8938                         {
8939                                 for (j = 0;j < surfacenumvertices;j++)
8940                                 {
8941                                         lm = surface->lightmapinfo->samples + offsets[j];
8942                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8943                                         VectorScale(lm, scale, c);
8944                                         if (surface->lightmapinfo->styles[1] != 255)
8945                                         {
8946                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8947                                                 lm += size3;
8948                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8949                                                 VectorMA(c, scale, lm, c);
8950                                                 if (surface->lightmapinfo->styles[2] != 255)
8951                                                 {
8952                                                         lm += size3;
8953                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8954                                                         VectorMA(c, scale, lm, c);
8955                                                         if (surface->lightmapinfo->styles[3] != 255)
8956                                                         {
8957                                                                 lm += size3;
8958                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8959                                                                 VectorMA(c, scale, lm, c);
8960                                                         }
8961                                                 }
8962                                         }
8963                                         c[0] >>= 7;
8964                                         c[1] >>= 7;
8965                                         c[2] >>= 7;
8966                                         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);
8967                                         numvertices++;
8968                                 }
8969                         }
8970                         else
8971                         {
8972                                 for (j = 0;j < surfacenumvertices;j++)
8973                                 {
8974                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8975                                         numvertices++;
8976                                 }
8977                         }
8978                 }
8979         }
8980
8981         // if vertices are deformed (sprite flares and things in maps, possibly
8982         // water waves, bulges and other deformations), modify the copied vertices
8983         // in place
8984         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8985         {
8986                 switch (deform->deform)
8987                 {
8988                 default:
8989                 case Q3DEFORM_PROJECTIONSHADOW:
8990                 case Q3DEFORM_TEXT0:
8991                 case Q3DEFORM_TEXT1:
8992                 case Q3DEFORM_TEXT2:
8993                 case Q3DEFORM_TEXT3:
8994                 case Q3DEFORM_TEXT4:
8995                 case Q3DEFORM_TEXT5:
8996                 case Q3DEFORM_TEXT6:
8997                 case Q3DEFORM_TEXT7:
8998                 case Q3DEFORM_NONE:
8999                         break;
9000                 case Q3DEFORM_AUTOSPRITE:
9001                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9002                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9003                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9004                         VectorNormalize(newforward);
9005                         VectorNormalize(newright);
9006                         VectorNormalize(newup);
9007 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9008 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9009 //                      rsurface.batchvertex3f_bufferoffset = 0;
9010 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9011 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9012 //                      rsurface.batchsvector3f_bufferoffset = 0;
9013 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9014 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9015 //                      rsurface.batchtvector3f_bufferoffset = 0;
9016 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9017 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9018 //                      rsurface.batchnormal3f_bufferoffset = 0;
9019                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9020                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9021                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9022                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9023                                 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);
9024                         // a single autosprite surface can contain multiple sprites...
9025                         for (j = 0;j < batchnumvertices - 3;j += 4)
9026                         {
9027                                 VectorClear(center);
9028                                 for (i = 0;i < 4;i++)
9029                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9030                                 VectorScale(center, 0.25f, center);
9031                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9032                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9033                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9034                                 for (i = 0;i < 4;i++)
9035                                 {
9036                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9037                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9038                                 }
9039                         }
9040                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9041                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9042                         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);
9043                         break;
9044                 case Q3DEFORM_AUTOSPRITE2:
9045                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9046                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9047                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9048                         VectorNormalize(newforward);
9049                         VectorNormalize(newright);
9050                         VectorNormalize(newup);
9051 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9052 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9053 //                      rsurface.batchvertex3f_bufferoffset = 0;
9054                         {
9055                                 const float *v1, *v2;
9056                                 vec3_t start, end;
9057                                 float f, l;
9058                                 struct
9059                                 {
9060                                         float length2;
9061                                         const float *v1;
9062                                         const float *v2;
9063                                 }
9064                                 shortest[2];
9065                                 memset(shortest, 0, sizeof(shortest));
9066                                 // a single autosprite surface can contain multiple sprites...
9067                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9068                                 {
9069                                         VectorClear(center);
9070                                         for (i = 0;i < 4;i++)
9071                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9072                                         VectorScale(center, 0.25f, center);
9073                                         // find the two shortest edges, then use them to define the
9074                                         // axis vectors for rotating around the central axis
9075                                         for (i = 0;i < 6;i++)
9076                                         {
9077                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9078                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9079                                                 l = VectorDistance2(v1, v2);
9080                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9081                                                 if (v1[2] != v2[2])
9082                                                         l += (1.0f / 1024.0f);
9083                                                 if (shortest[0].length2 > l || i == 0)
9084                                                 {
9085                                                         shortest[1] = shortest[0];
9086                                                         shortest[0].length2 = l;
9087                                                         shortest[0].v1 = v1;
9088                                                         shortest[0].v2 = v2;
9089                                                 }
9090                                                 else if (shortest[1].length2 > l || i == 1)
9091                                                 {
9092                                                         shortest[1].length2 = l;
9093                                                         shortest[1].v1 = v1;
9094                                                         shortest[1].v2 = v2;
9095                                                 }
9096                                         }
9097                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9098                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9099                                         // this calculates the right vector from the shortest edge
9100                                         // and the up vector from the edge midpoints
9101                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9102                                         VectorNormalize(right);
9103                                         VectorSubtract(end, start, up);
9104                                         VectorNormalize(up);
9105                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9106                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9107                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9108                                         VectorNegate(forward, forward);
9109                                         VectorReflect(forward, 0, up, forward);
9110                                         VectorNormalize(forward);
9111                                         CrossProduct(up, forward, newright);
9112                                         VectorNormalize(newright);
9113                                         // rotate the quad around the up axis vector, this is made
9114                                         // especially easy by the fact we know the quad is flat,
9115                                         // so we only have to subtract the center position and
9116                                         // measure distance along the right vector, and then
9117                                         // multiply that by the newright vector and add back the
9118                                         // center position
9119                                         // we also need to subtract the old position to undo the
9120                                         // displacement from the center, which we do with a
9121                                         // DotProduct, the subtraction/addition of center is also
9122                                         // optimized into DotProducts here
9123                                         l = DotProduct(right, center);
9124                                         for (i = 0;i < 4;i++)
9125                                         {
9126                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9127                                                 f = DotProduct(right, v1) - l;
9128                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9129                                         }
9130                                 }
9131                         }
9132                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9133                         {
9134 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9135 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9136 //                              rsurface.batchnormal3f_bufferoffset = 0;
9137                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9138                         }
9139                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9140                         {
9141 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9142 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9143 //                              rsurface.batchsvector3f_bufferoffset = 0;
9144 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9145 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9146 //                              rsurface.batchtvector3f_bufferoffset = 0;
9147                                 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);
9148                         }
9149                         break;
9150                 case Q3DEFORM_NORMAL:
9151                         // deform the normals to make reflections wavey
9152                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9153                         rsurface.batchnormal3f_vertexbuffer = NULL;
9154                         rsurface.batchnormal3f_bufferoffset = 0;
9155                         for (j = 0;j < batchnumvertices;j++)
9156                         {
9157                                 float vertex[3];
9158                                 float *normal = rsurface.batchnormal3f + 3*j;
9159                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9160                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9161                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9162                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9163                                 VectorNormalize(normal);
9164                         }
9165                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9166                         {
9167 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9168 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9169 //                              rsurface.batchsvector3f_bufferoffset = 0;
9170 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9171 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9172 //                              rsurface.batchtvector3f_bufferoffset = 0;
9173                                 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);
9174                         }
9175                         break;
9176                 case Q3DEFORM_WAVE:
9177                         // deform vertex array to make wavey water and flags and such
9178                         waveparms[0] = deform->waveparms[0];
9179                         waveparms[1] = deform->waveparms[1];
9180                         waveparms[2] = deform->waveparms[2];
9181                         waveparms[3] = deform->waveparms[3];
9182                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9183                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9184                         // this is how a divisor of vertex influence on deformation
9185                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9186                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9187 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9188 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9189 //                      rsurface.batchvertex3f_bufferoffset = 0;
9190 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9191 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9192 //                      rsurface.batchnormal3f_bufferoffset = 0;
9193                         for (j = 0;j < batchnumvertices;j++)
9194                         {
9195                                 // if the wavefunc depends on time, evaluate it per-vertex
9196                                 if (waveparms[3])
9197                                 {
9198                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9199                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9200                                 }
9201                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9202                         }
9203                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9204                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9205                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9206                         {
9207 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9208 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9209 //                              rsurface.batchsvector3f_bufferoffset = 0;
9210 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9211 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9212 //                              rsurface.batchtvector3f_bufferoffset = 0;
9213                                 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);
9214                         }
9215                         break;
9216                 case Q3DEFORM_BULGE:
9217                         // deform vertex array to make the surface have moving bulges
9218 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9219 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9220 //                      rsurface.batchvertex3f_bufferoffset = 0;
9221 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9222 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9223 //                      rsurface.batchnormal3f_bufferoffset = 0;
9224                         for (j = 0;j < batchnumvertices;j++)
9225                         {
9226                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9227                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9228                         }
9229                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9230                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9231                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9232                         {
9233 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9234 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9235 //                              rsurface.batchsvector3f_bufferoffset = 0;
9236 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9237 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9238 //                              rsurface.batchtvector3f_bufferoffset = 0;
9239                                 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);
9240                         }
9241                         break;
9242                 case Q3DEFORM_MOVE:
9243                         // deform vertex array
9244                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9245                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9246                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9247                         VectorScale(deform->parms, scale, waveparms);
9248 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9249 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9250 //                      rsurface.batchvertex3f_bufferoffset = 0;
9251                         for (j = 0;j < batchnumvertices;j++)
9252                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9253                         break;
9254                 }
9255         }
9256
9257         // generate texcoords based on the chosen texcoord source
9258         switch(rsurface.texture->tcgen.tcgen)
9259         {
9260         default:
9261         case Q3TCGEN_TEXTURE:
9262                 break;
9263         case Q3TCGEN_LIGHTMAP:
9264 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9265 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9266 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9267                 if (rsurface.batchtexcoordlightmap2f)
9268                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9269                 break;
9270         case Q3TCGEN_VECTOR:
9271 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9272 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9273 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9274                 for (j = 0;j < batchnumvertices;j++)
9275                 {
9276                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9277                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9278                 }
9279                 break;
9280         case Q3TCGEN_ENVIRONMENT:
9281                 // make environment reflections using a spheremap
9282                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9283                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9284                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9285                 for (j = 0;j < batchnumvertices;j++)
9286                 {
9287                         // identical to Q3A's method, but executed in worldspace so
9288                         // carried models can be shiny too
9289
9290                         float viewer[3], d, reflected[3], worldreflected[3];
9291
9292                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9293                         // VectorNormalize(viewer);
9294
9295                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9296
9297                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9298                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9299                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9300                         // note: this is proportinal to viewer, so we can normalize later
9301
9302                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9303                         VectorNormalize(worldreflected);
9304
9305                         // note: this sphere map only uses world x and z!
9306                         // so positive and negative y will LOOK THE SAME.
9307                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9308                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9309                 }
9310                 break;
9311         }
9312         // the only tcmod that needs software vertex processing is turbulent, so
9313         // check for it here and apply the changes if needed
9314         // and we only support that as the first one
9315         // (handling a mixture of turbulent and other tcmods would be problematic
9316         //  without punting it entirely to a software path)
9317         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9318         {
9319                 amplitude = rsurface.texture->tcmods[0].parms[1];
9320                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9321 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9322 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9323 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9324                 for (j = 0;j < batchnumvertices;j++)
9325                 {
9326                         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);
9327                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9328                 }
9329         }
9330
9331         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9332         {
9333                 // convert the modified arrays to vertex structs
9334 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9335 //              rsurface.batchvertexmeshbuffer = NULL;
9336                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9337                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9338                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9339                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9340                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9341                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9342                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9343                 {
9344                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9345                         {
9346                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9347                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9348                         }
9349                 }
9350                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9351                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9352                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9353                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9354                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9355                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9356                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9357                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9358                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9359         }
9360 }
9361
9362 void RSurf_DrawBatch(void)
9363 {
9364         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9365         // through the pipeline, killing it earlier in the pipeline would have
9366         // per-surface overhead rather than per-batch overhead, so it's best to
9367         // reject it here, before it hits glDraw.
9368         if (rsurface.batchnumtriangles == 0)
9369                 return;
9370 #if 0
9371         // batch debugging code
9372         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9373         {
9374                 int i;
9375                 int j;
9376                 int c;
9377                 const int *e;
9378                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9379                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9380                 {
9381                         c = e[i];
9382                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9383                         {
9384                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9385                                 {
9386                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9387                                                 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);
9388                                         break;
9389                                 }
9390                         }
9391                 }
9392         }
9393 #endif
9394         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);
9395 }
9396
9397 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9398 {
9399         // pick the closest matching water plane
9400         int planeindex, vertexindex, bestplaneindex = -1;
9401         float d, bestd;
9402         vec3_t vert;
9403         const float *v;
9404         r_waterstate_waterplane_t *p;
9405         qboolean prepared = false;
9406         bestd = 0;
9407         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9408         {
9409                 if(p->camera_entity != rsurface.texture->camera_entity)
9410                         continue;
9411                 d = 0;
9412                 if(!prepared)
9413                 {
9414                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9415                         prepared = true;
9416                         if(rsurface.batchnumvertices == 0)
9417                                 break;
9418                 }
9419                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9420                 {
9421                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9422                         d += fabs(PlaneDiff(vert, &p->plane));
9423                 }
9424                 if (bestd > d || bestplaneindex < 0)
9425                 {
9426                         bestd = d;
9427                         bestplaneindex = planeindex;
9428                 }
9429         }
9430         return bestplaneindex;
9431         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9432         // this situation though, as it might be better to render single larger
9433         // batches with useless stuff (backface culled for example) than to
9434         // render multiple smaller batches
9435 }
9436
9437 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9438 {
9439         int i;
9440         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9441         rsurface.passcolor4f_vertexbuffer = 0;
9442         rsurface.passcolor4f_bufferoffset = 0;
9443         for (i = 0;i < rsurface.batchnumvertices;i++)
9444                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9445 }
9446
9447 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9448 {
9449         int i;
9450         float f;
9451         const float *v;
9452         const float *c;
9453         float *c2;
9454         if (rsurface.passcolor4f)
9455         {
9456                 // generate color arrays
9457                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9458                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9459                 rsurface.passcolor4f_vertexbuffer = 0;
9460                 rsurface.passcolor4f_bufferoffset = 0;
9461                 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)
9462                 {
9463                         f = RSurf_FogVertex(v);
9464                         c2[0] = c[0] * f;
9465                         c2[1] = c[1] * f;
9466                         c2[2] = c[2] * f;
9467                         c2[3] = c[3];
9468                 }
9469         }
9470         else
9471         {
9472                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9473                 rsurface.passcolor4f_vertexbuffer = 0;
9474                 rsurface.passcolor4f_bufferoffset = 0;
9475                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9476                 {
9477                         f = RSurf_FogVertex(v);
9478                         c2[0] = f;
9479                         c2[1] = f;
9480                         c2[2] = f;
9481                         c2[3] = 1;
9482                 }
9483         }
9484 }
9485
9486 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9487 {
9488         int i;
9489         float f;
9490         const float *v;
9491         const float *c;
9492         float *c2;
9493         if (!rsurface.passcolor4f)
9494                 return;
9495         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9496         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9497         rsurface.passcolor4f_vertexbuffer = 0;
9498         rsurface.passcolor4f_bufferoffset = 0;
9499         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)
9500         {
9501                 f = RSurf_FogVertex(v);
9502                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9503                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9504                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9505                 c2[3] = c[3];
9506         }
9507 }
9508
9509 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9510 {
9511         int i;
9512         const float *c;
9513         float *c2;
9514         if (!rsurface.passcolor4f)
9515                 return;
9516         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9517         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9518         rsurface.passcolor4f_vertexbuffer = 0;
9519         rsurface.passcolor4f_bufferoffset = 0;
9520         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9521         {
9522                 c2[0] = c[0] * r;
9523                 c2[1] = c[1] * g;
9524                 c2[2] = c[2] * b;
9525                 c2[3] = c[3] * a;
9526         }
9527 }
9528
9529 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9530 {
9531         int i;
9532         const float *c;
9533         float *c2;
9534         if (!rsurface.passcolor4f)
9535                 return;
9536         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9537         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9538         rsurface.passcolor4f_vertexbuffer = 0;
9539         rsurface.passcolor4f_bufferoffset = 0;
9540         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9541         {
9542                 c2[0] = c[0] + r_refdef.scene.ambient;
9543                 c2[1] = c[1] + r_refdef.scene.ambient;
9544                 c2[2] = c[2] + r_refdef.scene.ambient;
9545                 c2[3] = c[3];
9546         }
9547 }
9548
9549 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9550 {
9551         // TODO: optimize
9552         rsurface.passcolor4f = NULL;
9553         rsurface.passcolor4f_vertexbuffer = 0;
9554         rsurface.passcolor4f_bufferoffset = 0;
9555         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9556         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9557         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9558         GL_Color(r, g, b, a);
9559         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9560         RSurf_DrawBatch();
9561 }
9562
9563 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9564 {
9565         // TODO: optimize applyfog && applycolor case
9566         // just apply fog if necessary, and tint the fog color array if necessary
9567         rsurface.passcolor4f = NULL;
9568         rsurface.passcolor4f_vertexbuffer = 0;
9569         rsurface.passcolor4f_bufferoffset = 0;
9570         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9571         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9572         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9573         GL_Color(r, g, b, a);
9574         RSurf_DrawBatch();
9575 }
9576
9577 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9578 {
9579         // TODO: optimize
9580         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9581         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9582         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9583         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9584         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9585         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9586         GL_Color(r, g, b, a);
9587         RSurf_DrawBatch();
9588 }
9589
9590 static void RSurf_DrawBatch_GL11_ClampColor(void)
9591 {
9592         int i;
9593         const float *c1;
9594         float *c2;
9595         if (!rsurface.passcolor4f)
9596                 return;
9597         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9598         {
9599                 c2[0] = bound(0.0f, c1[0], 1.0f);
9600                 c2[1] = bound(0.0f, c1[1], 1.0f);
9601                 c2[2] = bound(0.0f, c1[2], 1.0f);
9602                 c2[3] = bound(0.0f, c1[3], 1.0f);
9603         }
9604 }
9605
9606 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9607 {
9608         int i;
9609         float f;
9610         const float *v;
9611         const float *n;
9612         float *c;
9613         //vec3_t eyedir;
9614
9615         // fake shading
9616         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9617         rsurface.passcolor4f_vertexbuffer = 0;
9618         rsurface.passcolor4f_bufferoffset = 0;
9619         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)
9620         {
9621                 f = -DotProduct(r_refdef.view.forward, n);
9622                 f = max(0, f);
9623                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9624                 f *= r_refdef.lightmapintensity;
9625                 Vector4Set(c, f, f, f, 1);
9626         }
9627 }
9628
9629 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9630 {
9631         RSurf_DrawBatch_GL11_ApplyFakeLight();
9632         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9633         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9634         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9635         GL_Color(r, g, b, a);
9636         RSurf_DrawBatch();
9637 }
9638
9639 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9640 {
9641         int i;
9642         float f;
9643         float alpha;
9644         const float *v;
9645         const float *n;
9646         float *c;
9647         vec3_t ambientcolor;
9648         vec3_t diffusecolor;
9649         vec3_t lightdir;
9650         // TODO: optimize
9651         // model lighting
9652         VectorCopy(rsurface.modellight_lightdir, lightdir);
9653         f = 0.5f * r_refdef.lightmapintensity;
9654         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9655         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9656         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9657         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9658         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9659         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9660         alpha = *a;
9661         if (VectorLength2(diffusecolor) > 0)
9662         {
9663                 // q3-style directional shading
9664                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9665                 rsurface.passcolor4f_vertexbuffer = 0;
9666                 rsurface.passcolor4f_bufferoffset = 0;
9667                 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)
9668                 {
9669                         if ((f = DotProduct(n, lightdir)) > 0)
9670                                 VectorMA(ambientcolor, f, diffusecolor, c);
9671                         else
9672                                 VectorCopy(ambientcolor, c);
9673                         c[3] = alpha;
9674                 }
9675                 *r = 1;
9676                 *g = 1;
9677                 *b = 1;
9678                 *a = 1;
9679                 *applycolor = false;
9680         }
9681         else
9682         {
9683                 *r = ambientcolor[0];
9684                 *g = ambientcolor[1];
9685                 *b = ambientcolor[2];
9686                 rsurface.passcolor4f = NULL;
9687                 rsurface.passcolor4f_vertexbuffer = 0;
9688                 rsurface.passcolor4f_bufferoffset = 0;
9689         }
9690 }
9691
9692 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9693 {
9694         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9695         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9696         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9697         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9698         GL_Color(r, g, b, a);
9699         RSurf_DrawBatch();
9700 }
9701
9702 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9703 {
9704         int i;
9705         float f;
9706         const float *v;
9707         float *c;
9708
9709         // fake shading
9710         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9711         rsurface.passcolor4f_vertexbuffer = 0;
9712         rsurface.passcolor4f_bufferoffset = 0;
9713
9714         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9715         {
9716                 f = 1 - RSurf_FogVertex(v);
9717                 c[0] = r;
9718                 c[1] = g;
9719                 c[2] = b;
9720                 c[3] = f * a;
9721         }
9722 }
9723
9724 void RSurf_SetupDepthAndCulling(void)
9725 {
9726         // submodels are biased to avoid z-fighting with world surfaces that they
9727         // may be exactly overlapping (avoids z-fighting artifacts on certain
9728         // doors and things in Quake maps)
9729         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9730         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9731         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9732         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9733 }
9734
9735 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9736 {
9737         // transparent sky would be ridiculous
9738         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9739                 return;
9740         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9741         skyrenderlater = true;
9742         RSurf_SetupDepthAndCulling();
9743         GL_DepthMask(true);
9744         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9745         // skymasking on them, and Quake3 never did sky masking (unlike
9746         // software Quake and software Quake2), so disable the sky masking
9747         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9748         // and skymasking also looks very bad when noclipping outside the
9749         // level, so don't use it then either.
9750         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9751         {
9752                 R_Mesh_ResetTextureState();
9753                 if (skyrendermasked)
9754                 {
9755                         R_SetupShader_DepthOrShadow(false);
9756                         // depth-only (masking)
9757                         GL_ColorMask(0,0,0,0);
9758                         // just to make sure that braindead drivers don't draw
9759                         // anything despite that colormask...
9760                         GL_BlendFunc(GL_ZERO, GL_ONE);
9761                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9762                         if (rsurface.batchvertex3fbuffer)
9763                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9764                         else
9765                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9766                 }
9767                 else
9768                 {
9769                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9770                         // fog sky
9771                         GL_BlendFunc(GL_ONE, GL_ZERO);
9772                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9773                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9774                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9775                 }
9776                 RSurf_DrawBatch();
9777                 if (skyrendermasked)
9778                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9779         }
9780         R_Mesh_ResetTextureState();
9781         GL_Color(1, 1, 1, 1);
9782 }
9783
9784 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9785 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9786 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9787 {
9788         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9789                 return;
9790         if (prepass)
9791         {
9792                 // render screenspace normalmap to texture
9793                 GL_DepthMask(true);
9794                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9795                 RSurf_DrawBatch();
9796         }
9797
9798         // bind lightmap texture
9799
9800         // water/refraction/reflection/camera surfaces have to be handled specially
9801         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9802         {
9803                 int start, end, startplaneindex;
9804                 for (start = 0;start < texturenumsurfaces;start = end)
9805                 {
9806                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9807                         if(startplaneindex < 0)
9808                         {
9809                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9810                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9811                                 end = start + 1;
9812                                 continue;
9813                         }
9814                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9815                                 ;
9816                         // now that we have a batch using the same planeindex, render it
9817                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9818                         {
9819                                 // render water or distortion background
9820                                 GL_DepthMask(true);
9821                                 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);
9822                                 RSurf_DrawBatch();
9823                                 // blend surface on top
9824                                 GL_DepthMask(false);
9825                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9826                                 RSurf_DrawBatch();
9827                         }
9828                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9829                         {
9830                                 // render surface with reflection texture as input
9831                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9832                                 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);
9833                                 RSurf_DrawBatch();
9834                         }
9835                 }
9836                 return;
9837         }
9838
9839         // render surface batch normally
9840         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9841         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);
9842         RSurf_DrawBatch();
9843 }
9844
9845 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9846 {
9847         // OpenGL 1.3 path - anything not completely ancient
9848         qboolean applycolor;
9849         qboolean applyfog;
9850         int layerindex;
9851         const texturelayer_t *layer;
9852         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);
9853         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9854
9855         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9856         {
9857                 vec4_t layercolor;
9858                 int layertexrgbscale;
9859                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9860                 {
9861                         if (layerindex == 0)
9862                                 GL_AlphaTest(true);
9863                         else
9864                         {
9865                                 GL_AlphaTest(false);
9866                                 GL_DepthFunc(GL_EQUAL);
9867                         }
9868                 }
9869                 GL_DepthMask(layer->depthmask && writedepth);
9870                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9871                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9872                 {
9873                         layertexrgbscale = 4;
9874                         VectorScale(layer->color, 0.25f, layercolor);
9875                 }
9876                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9877                 {
9878                         layertexrgbscale = 2;
9879                         VectorScale(layer->color, 0.5f, layercolor);
9880                 }
9881                 else
9882                 {
9883                         layertexrgbscale = 1;
9884                         VectorScale(layer->color, 1.0f, layercolor);
9885                 }
9886                 layercolor[3] = layer->color[3];
9887                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9888                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9889                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9890                 switch (layer->type)
9891                 {
9892                 case TEXTURELAYERTYPE_LITTEXTURE:
9893                         // single-pass lightmapped texture with 2x rgbscale
9894                         R_Mesh_TexBind(0, r_texture_white);
9895                         R_Mesh_TexMatrix(0, NULL);
9896                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9897                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9898                         R_Mesh_TexBind(1, layer->texture);
9899                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9900                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9901                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9902                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9903                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9904                         else if (FAKELIGHT_ENABLED)
9905                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9906                         else if (rsurface.uselightmaptexture)
9907                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9908                         else
9909                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9910                         break;
9911                 case TEXTURELAYERTYPE_TEXTURE:
9912                         // singletexture unlit texture with transparency support
9913                         R_Mesh_TexBind(0, layer->texture);
9914                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9915                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9916                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9917                         R_Mesh_TexBind(1, 0);
9918                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9919                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9920                         break;
9921                 case TEXTURELAYERTYPE_FOG:
9922                         // singletexture fogging
9923                         if (layer->texture)
9924                         {
9925                                 R_Mesh_TexBind(0, layer->texture);
9926                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9927                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9928                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9929                         }
9930                         else
9931                         {
9932                                 R_Mesh_TexBind(0, 0);
9933                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9934                         }
9935                         R_Mesh_TexBind(1, 0);
9936                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9937                         // generate a color array for the fog pass
9938                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9939                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9940                         RSurf_DrawBatch();
9941                         break;
9942                 default:
9943                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9944                 }
9945         }
9946         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9947         {
9948                 GL_DepthFunc(GL_LEQUAL);
9949                 GL_AlphaTest(false);
9950         }
9951 }
9952
9953 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9954 {
9955         // OpenGL 1.1 - crusty old voodoo path
9956         qboolean applyfog;
9957         int layerindex;
9958         const texturelayer_t *layer;
9959         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);
9960         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9961
9962         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9963         {
9964                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9965                 {
9966                         if (layerindex == 0)
9967                                 GL_AlphaTest(true);
9968                         else
9969                         {
9970                                 GL_AlphaTest(false);
9971                                 GL_DepthFunc(GL_EQUAL);
9972                         }
9973                 }
9974                 GL_DepthMask(layer->depthmask && writedepth);
9975                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9976                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9977                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9978                 switch (layer->type)
9979                 {
9980                 case TEXTURELAYERTYPE_LITTEXTURE:
9981                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9982                         {
9983                                 // two-pass lit texture with 2x rgbscale
9984                                 // first the lightmap pass
9985                                 R_Mesh_TexBind(0, r_texture_white);
9986                                 R_Mesh_TexMatrix(0, NULL);
9987                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9988                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9989                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9990                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9991                                 else if (FAKELIGHT_ENABLED)
9992                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9993                                 else if (rsurface.uselightmaptexture)
9994                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9995                                 else
9996                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9997                                 // then apply the texture to it
9998                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9999                                 R_Mesh_TexBind(0, layer->texture);
10000                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10001                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10002                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10003                                 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);
10004                         }
10005                         else
10006                         {
10007                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10008                                 R_Mesh_TexBind(0, layer->texture);
10009                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10010                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10011                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10012                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10013                                         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);
10014                                 else
10015                                         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);
10016                         }
10017                         break;
10018                 case TEXTURELAYERTYPE_TEXTURE:
10019                         // singletexture unlit texture with transparency support
10020                         R_Mesh_TexBind(0, layer->texture);
10021                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10022                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10023                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10024                         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);
10025                         break;
10026                 case TEXTURELAYERTYPE_FOG:
10027                         // singletexture fogging
10028                         if (layer->texture)
10029                         {
10030                                 R_Mesh_TexBind(0, layer->texture);
10031                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10032                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10033                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10034                         }
10035                         else
10036                         {
10037                                 R_Mesh_TexBind(0, 0);
10038                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10039                         }
10040                         // generate a color array for the fog pass
10041                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10042                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10043                         RSurf_DrawBatch();
10044                         break;
10045                 default:
10046                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10047                 }
10048         }
10049         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10050         {
10051                 GL_DepthFunc(GL_LEQUAL);
10052                 GL_AlphaTest(false);
10053         }
10054 }
10055
10056 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10057 {
10058         int vi;
10059         int j;
10060         r_vertexgeneric_t *batchvertex;
10061         float c[4];
10062
10063 //      R_Mesh_ResetTextureState();
10064         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10065
10066         if(rsurface.texture && rsurface.texture->currentskinframe)
10067         {
10068                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10069                 c[3] *= rsurface.texture->currentalpha;
10070         }
10071         else
10072         {
10073                 c[0] = 1;
10074                 c[1] = 0;
10075                 c[2] = 1;
10076                 c[3] = 1;
10077         }
10078
10079         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10080         {
10081                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10082                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10083                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10084         }
10085
10086         // brighten it up (as texture value 127 means "unlit")
10087         c[0] *= 2 * r_refdef.view.colorscale;
10088         c[1] *= 2 * r_refdef.view.colorscale;
10089         c[2] *= 2 * r_refdef.view.colorscale;
10090
10091         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10092                 c[3] *= r_wateralpha.value;
10093
10094         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10095         {
10096                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10097                 GL_DepthMask(false);
10098         }
10099         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10100         {
10101                 GL_BlendFunc(GL_ONE, GL_ONE);
10102                 GL_DepthMask(false);
10103         }
10104         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10105         {
10106                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10107                 GL_DepthMask(false);
10108         }
10109         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10110         {
10111                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10112                 GL_DepthMask(false);
10113         }
10114         else
10115         {
10116                 GL_BlendFunc(GL_ONE, GL_ZERO);
10117                 GL_DepthMask(writedepth);
10118         }
10119
10120         if (r_showsurfaces.integer == 3)
10121         {
10122                 rsurface.passcolor4f = NULL;
10123
10124                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10125                 {
10126                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10127
10128                         rsurface.passcolor4f = NULL;
10129                         rsurface.passcolor4f_vertexbuffer = 0;
10130                         rsurface.passcolor4f_bufferoffset = 0;
10131                 }
10132                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10133                 {
10134                         qboolean applycolor = true;
10135                         float one = 1.0;
10136
10137                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10138
10139                         r_refdef.lightmapintensity = 1;
10140                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10141                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10142                 }
10143                 else if (FAKELIGHT_ENABLED)
10144                 {
10145                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10146
10147                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10148                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10149                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10150                 }
10151                 else
10152                 {
10153                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10154
10155                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10156                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10157                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10158                 }
10159
10160                 if(!rsurface.passcolor4f)
10161                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10162
10163                 RSurf_DrawBatch_GL11_ApplyAmbient();
10164                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10165                 if(r_refdef.fogenabled)
10166                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10167                 RSurf_DrawBatch_GL11_ClampColor();
10168
10169                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10170                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10171                 RSurf_DrawBatch();
10172         }
10173         else if (!r_refdef.view.showdebug)
10174         {
10175                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10176                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10177                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10178                 {
10179                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10180                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10181                 }
10182                 R_Mesh_PrepareVertices_Generic_Unlock();
10183                 RSurf_DrawBatch();
10184         }
10185         else if (r_showsurfaces.integer == 4)
10186         {
10187                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10188                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10189                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10190                 {
10191                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10192                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10193                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10194                 }
10195                 R_Mesh_PrepareVertices_Generic_Unlock();
10196                 RSurf_DrawBatch();
10197         }
10198         else if (r_showsurfaces.integer == 2)
10199         {
10200                 const int *e;
10201                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10202                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10203                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10204                 {
10205                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10206                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10207                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10208                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10209                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10210                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10211                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10212                 }
10213                 R_Mesh_PrepareVertices_Generic_Unlock();
10214                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10215         }
10216         else
10217         {
10218                 int texturesurfaceindex;
10219                 int k;
10220                 const msurface_t *surface;
10221                 float surfacecolor4f[4];
10222                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10223                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10224                 vi = 0;
10225                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10226                 {
10227                         surface = texturesurfacelist[texturesurfaceindex];
10228                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10229                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10230                         for (j = 0;j < surface->num_vertices;j++)
10231                         {
10232                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10233                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10234                                 vi++;
10235                         }
10236                 }
10237                 R_Mesh_PrepareVertices_Generic_Unlock();
10238                 RSurf_DrawBatch();
10239         }
10240 }
10241
10242 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10243 {
10244         CHECKGLERROR
10245         RSurf_SetupDepthAndCulling();
10246         if (r_showsurfaces.integer)
10247         {
10248                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10249                 return;
10250         }
10251         switch (vid.renderpath)
10252         {
10253         case RENDERPATH_GL20:
10254         case RENDERPATH_D3D9:
10255         case RENDERPATH_D3D10:
10256         case RENDERPATH_D3D11:
10257         case RENDERPATH_SOFT:
10258         case RENDERPATH_GLES2:
10259                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10260                 break;
10261         case RENDERPATH_GL13:
10262         case RENDERPATH_GLES1:
10263                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10264                 break;
10265         case RENDERPATH_GL11:
10266                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10267                 break;
10268         }
10269         CHECKGLERROR
10270 }
10271
10272 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10273 {
10274         CHECKGLERROR
10275         RSurf_SetupDepthAndCulling();
10276         if (r_showsurfaces.integer)
10277         {
10278                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10279                 return;
10280         }
10281         switch (vid.renderpath)
10282         {
10283         case RENDERPATH_GL20:
10284         case RENDERPATH_D3D9:
10285         case RENDERPATH_D3D10:
10286         case RENDERPATH_D3D11:
10287         case RENDERPATH_SOFT:
10288         case RENDERPATH_GLES2:
10289                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10290                 break;
10291         case RENDERPATH_GL13:
10292         case RENDERPATH_GLES1:
10293                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10294                 break;
10295         case RENDERPATH_GL11:
10296                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10297                 break;
10298         }
10299         CHECKGLERROR
10300 }
10301
10302 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10303 {
10304         int i, j;
10305         int texturenumsurfaces, endsurface;
10306         texture_t *texture;
10307         const msurface_t *surface;
10308         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10309
10310         // if the model is static it doesn't matter what value we give for
10311         // wantnormals and wanttangents, so this logic uses only rules applicable
10312         // to a model, knowing that they are meaningless otherwise
10313         if (ent == r_refdef.scene.worldentity)
10314                 RSurf_ActiveWorldEntity();
10315         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10316                 RSurf_ActiveModelEntity(ent, false, false, false);
10317         else
10318         {
10319                 switch (vid.renderpath)
10320                 {
10321                 case RENDERPATH_GL20:
10322                 case RENDERPATH_D3D9:
10323                 case RENDERPATH_D3D10:
10324                 case RENDERPATH_D3D11:
10325                 case RENDERPATH_SOFT:
10326                 case RENDERPATH_GLES2:
10327                         RSurf_ActiveModelEntity(ent, true, true, false);
10328                         break;
10329                 case RENDERPATH_GL11:
10330                 case RENDERPATH_GL13:
10331                 case RENDERPATH_GLES1:
10332                         RSurf_ActiveModelEntity(ent, true, false, false);
10333                         break;
10334                 }
10335         }
10336
10337         if (r_transparentdepthmasking.integer)
10338         {
10339                 qboolean setup = false;
10340                 for (i = 0;i < numsurfaces;i = j)
10341                 {
10342                         j = i + 1;
10343                         surface = rsurface.modelsurfaces + surfacelist[i];
10344                         texture = surface->texture;
10345                         rsurface.texture = R_GetCurrentTexture(texture);
10346                         rsurface.lightmaptexture = NULL;
10347                         rsurface.deluxemaptexture = NULL;
10348                         rsurface.uselightmaptexture = false;
10349                         // scan ahead until we find a different texture
10350                         endsurface = min(i + 1024, numsurfaces);
10351                         texturenumsurfaces = 0;
10352                         texturesurfacelist[texturenumsurfaces++] = surface;
10353                         for (;j < endsurface;j++)
10354                         {
10355                                 surface = rsurface.modelsurfaces + surfacelist[j];
10356                                 if (texture != surface->texture)
10357                                         break;
10358                                 texturesurfacelist[texturenumsurfaces++] = surface;
10359                         }
10360                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10361                                 continue;
10362                         // render the range of surfaces as depth
10363                         if (!setup)
10364                         {
10365                                 setup = true;
10366                                 GL_ColorMask(0,0,0,0);
10367                                 GL_Color(1,1,1,1);
10368                                 GL_DepthTest(true);
10369                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10370                                 GL_DepthMask(true);
10371 //                              R_Mesh_ResetTextureState();
10372                                 R_SetupShader_DepthOrShadow(false);
10373                         }
10374                         RSurf_SetupDepthAndCulling();
10375                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10376                         if (rsurface.batchvertex3fbuffer)
10377                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10378                         else
10379                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10380                         RSurf_DrawBatch();
10381                 }
10382                 if (setup)
10383                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10384         }
10385
10386         for (i = 0;i < numsurfaces;i = j)
10387         {
10388                 j = i + 1;
10389                 surface = rsurface.modelsurfaces + surfacelist[i];
10390                 texture = surface->texture;
10391                 rsurface.texture = R_GetCurrentTexture(texture);
10392                 // scan ahead until we find a different texture
10393                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10394                 texturenumsurfaces = 0;
10395                 texturesurfacelist[texturenumsurfaces++] = surface;
10396                 if(FAKELIGHT_ENABLED)
10397                 {
10398                         rsurface.lightmaptexture = NULL;
10399                         rsurface.deluxemaptexture = NULL;
10400                         rsurface.uselightmaptexture = false;
10401                         for (;j < endsurface;j++)
10402                         {
10403                                 surface = rsurface.modelsurfaces + surfacelist[j];
10404                                 if (texture != surface->texture)
10405                                         break;
10406                                 texturesurfacelist[texturenumsurfaces++] = surface;
10407                         }
10408                 }
10409                 else
10410                 {
10411                         rsurface.lightmaptexture = surface->lightmaptexture;
10412                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10413                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10414                         for (;j < endsurface;j++)
10415                         {
10416                                 surface = rsurface.modelsurfaces + surfacelist[j];
10417                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10418                                         break;
10419                                 texturesurfacelist[texturenumsurfaces++] = surface;
10420                         }
10421                 }
10422                 // render the range of surfaces
10423                 if (ent == r_refdef.scene.worldentity)
10424                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10425                 else
10426                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10427         }
10428         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10429 }
10430
10431 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10432 {
10433         // transparent surfaces get pushed off into the transparent queue
10434         int surfacelistindex;
10435         const msurface_t *surface;
10436         vec3_t tempcenter, center;
10437         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10438         {
10439                 surface = texturesurfacelist[surfacelistindex];
10440                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10441                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10442                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10443                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10444                 if (queueentity->transparent_offset) // transparent offset
10445                 {
10446                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10447                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10448                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10449                 }
10450                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10451         }
10452 }
10453
10454 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10455 {
10456         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10457                 return;
10458         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10459                 return;
10460         RSurf_SetupDepthAndCulling();
10461         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10462         if (rsurface.batchvertex3fbuffer)
10463                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10464         else
10465                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10466         RSurf_DrawBatch();
10467 }
10468
10469 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10470 {
10471         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10472         CHECKGLERROR
10473         if (depthonly)
10474                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10475         else if (prepass)
10476         {
10477                 if (!rsurface.texture->currentnumlayers)
10478                         return;
10479                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10480                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10481                 else
10482                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10483         }
10484         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10485                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10486         else if (!rsurface.texture->currentnumlayers)
10487                 return;
10488         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10489         {
10490                 // in the deferred case, transparent surfaces were queued during prepass
10491                 if (!r_shadow_usingdeferredprepass)
10492                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10493         }
10494         else
10495         {
10496                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10497                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10498         }
10499         CHECKGLERROR
10500 }
10501
10502 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10503 {
10504         int i, j;
10505         texture_t *texture;
10506         R_FrameData_SetMark();
10507         // break the surface list down into batches by texture and use of lightmapping
10508         for (i = 0;i < numsurfaces;i = j)
10509         {
10510                 j = i + 1;
10511                 // texture is the base texture pointer, rsurface.texture is the
10512                 // current frame/skin the texture is directing us to use (for example
10513                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10514                 // use skin 1 instead)
10515                 texture = surfacelist[i]->texture;
10516                 rsurface.texture = R_GetCurrentTexture(texture);
10517                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10518                 {
10519                         // if this texture is not the kind we want, skip ahead to the next one
10520                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10521                                 ;
10522                         continue;
10523                 }
10524                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10525                 {
10526                         rsurface.lightmaptexture = NULL;
10527                         rsurface.deluxemaptexture = NULL;
10528                         rsurface.uselightmaptexture = false;
10529                         // simply scan ahead until we find a different texture or lightmap state
10530                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10531                                 ;
10532                 }
10533                 else
10534                 {
10535                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10536                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10537                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10538                         // simply scan ahead until we find a different texture or lightmap state
10539                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10540                                 ;
10541                 }
10542                 // render the range of surfaces
10543                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10544         }
10545         R_FrameData_ReturnToMark();
10546 }
10547
10548 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10549 {
10550         CHECKGLERROR
10551         if (depthonly)
10552                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10553         else if (prepass)
10554         {
10555                 if (!rsurface.texture->currentnumlayers)
10556                         return;
10557                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10558                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10559                 else
10560                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10561         }
10562         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10563                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10564         else if (!rsurface.texture->currentnumlayers)
10565                 return;
10566         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10567         {
10568                 // in the deferred case, transparent surfaces were queued during prepass
10569                 if (!r_shadow_usingdeferredprepass)
10570                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10571         }
10572         else
10573         {
10574                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10575                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10576         }
10577         CHECKGLERROR
10578 }
10579
10580 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10581 {
10582         int i, j;
10583         texture_t *texture;
10584         R_FrameData_SetMark();
10585         // break the surface list down into batches by texture and use of lightmapping
10586         for (i = 0;i < numsurfaces;i = j)
10587         {
10588                 j = i + 1;
10589                 // texture is the base texture pointer, rsurface.texture is the
10590                 // current frame/skin the texture is directing us to use (for example
10591                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10592                 // use skin 1 instead)
10593                 texture = surfacelist[i]->texture;
10594                 rsurface.texture = R_GetCurrentTexture(texture);
10595                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10596                 {
10597                         // if this texture is not the kind we want, skip ahead to the next one
10598                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10599                                 ;
10600                         continue;
10601                 }
10602                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10603                 {
10604                         rsurface.lightmaptexture = NULL;
10605                         rsurface.deluxemaptexture = NULL;
10606                         rsurface.uselightmaptexture = false;
10607                         // simply scan ahead until we find a different texture or lightmap state
10608                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10609                                 ;
10610                 }
10611                 else
10612                 {
10613                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10614                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10615                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10616                         // simply scan ahead until we find a different texture or lightmap state
10617                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10618                                 ;
10619                 }
10620                 // render the range of surfaces
10621                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10622         }
10623         R_FrameData_ReturnToMark();
10624 }
10625
10626 float locboxvertex3f[6*4*3] =
10627 {
10628         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10629         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10630         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10631         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10632         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10633         1,0,0, 0,0,0, 0,1,0, 1,1,0
10634 };
10635
10636 unsigned short locboxelements[6*2*3] =
10637 {
10638          0, 1, 2, 0, 2, 3,
10639          4, 5, 6, 4, 6, 7,
10640          8, 9,10, 8,10,11,
10641         12,13,14, 12,14,15,
10642         16,17,18, 16,18,19,
10643         20,21,22, 20,22,23
10644 };
10645
10646 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10647 {
10648         int i, j;
10649         cl_locnode_t *loc = (cl_locnode_t *)ent;
10650         vec3_t mins, size;
10651         float vertex3f[6*4*3];
10652         CHECKGLERROR
10653         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10654         GL_DepthMask(false);
10655         GL_DepthRange(0, 1);
10656         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10657         GL_DepthTest(true);
10658         GL_CullFace(GL_NONE);
10659         R_EntityMatrix(&identitymatrix);
10660
10661 //      R_Mesh_ResetTextureState();
10662
10663         i = surfacelist[0];
10664         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10665                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10666                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10667                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10668
10669         if (VectorCompare(loc->mins, loc->maxs))
10670         {
10671                 VectorSet(size, 2, 2, 2);
10672                 VectorMA(loc->mins, -0.5f, size, mins);
10673         }
10674         else
10675         {
10676                 VectorCopy(loc->mins, mins);
10677                 VectorSubtract(loc->maxs, loc->mins, size);
10678         }
10679
10680         for (i = 0;i < 6*4*3;)
10681                 for (j = 0;j < 3;j++, i++)
10682                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10683
10684         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10685         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10686         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10687 }
10688
10689 void R_DrawLocs(void)
10690 {
10691         int index;
10692         cl_locnode_t *loc, *nearestloc;
10693         vec3_t center;
10694         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10695         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10696         {
10697                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10698                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10699         }
10700 }
10701
10702 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10703 {
10704         if (decalsystem->decals)
10705                 Mem_Free(decalsystem->decals);
10706         memset(decalsystem, 0, sizeof(*decalsystem));
10707 }
10708
10709 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)
10710 {
10711         tridecal_t *decal;
10712         tridecal_t *decals;
10713         int i;
10714
10715         // expand or initialize the system
10716         if (decalsystem->maxdecals <= decalsystem->numdecals)
10717         {
10718                 decalsystem_t old = *decalsystem;
10719                 qboolean useshortelements;
10720                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10721                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10722                 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)));
10723                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10724                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10725                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10726                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10727                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10728                 if (decalsystem->numdecals)
10729                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10730                 if (old.decals)
10731                         Mem_Free(old.decals);
10732                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10733                         decalsystem->element3i[i] = i;
10734                 if (useshortelements)
10735                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10736                                 decalsystem->element3s[i] = i;
10737         }
10738
10739         // grab a decal and search for another free slot for the next one
10740         decals = decalsystem->decals;
10741         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10742         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10743                 ;
10744         decalsystem->freedecal = i;
10745         if (decalsystem->numdecals <= i)
10746                 decalsystem->numdecals = i + 1;
10747
10748         // initialize the decal
10749         decal->lived = 0;
10750         decal->triangleindex = triangleindex;
10751         decal->surfaceindex = surfaceindex;
10752         decal->decalsequence = decalsequence;
10753         decal->color4f[0][0] = c0[0];
10754         decal->color4f[0][1] = c0[1];
10755         decal->color4f[0][2] = c0[2];
10756         decal->color4f[0][3] = 1;
10757         decal->color4f[1][0] = c1[0];
10758         decal->color4f[1][1] = c1[1];
10759         decal->color4f[1][2] = c1[2];
10760         decal->color4f[1][3] = 1;
10761         decal->color4f[2][0] = c2[0];
10762         decal->color4f[2][1] = c2[1];
10763         decal->color4f[2][2] = c2[2];
10764         decal->color4f[2][3] = 1;
10765         decal->vertex3f[0][0] = v0[0];
10766         decal->vertex3f[0][1] = v0[1];
10767         decal->vertex3f[0][2] = v0[2];
10768         decal->vertex3f[1][0] = v1[0];
10769         decal->vertex3f[1][1] = v1[1];
10770         decal->vertex3f[1][2] = v1[2];
10771         decal->vertex3f[2][0] = v2[0];
10772         decal->vertex3f[2][1] = v2[1];
10773         decal->vertex3f[2][2] = v2[2];
10774         decal->texcoord2f[0][0] = t0[0];
10775         decal->texcoord2f[0][1] = t0[1];
10776         decal->texcoord2f[1][0] = t1[0];
10777         decal->texcoord2f[1][1] = t1[1];
10778         decal->texcoord2f[2][0] = t2[0];
10779         decal->texcoord2f[2][1] = t2[1];
10780         TriangleNormal(v0, v1, v2, decal->plane);
10781         VectorNormalize(decal->plane);
10782         decal->plane[3] = DotProduct(v0, decal->plane);
10783 }
10784
10785 extern cvar_t cl_decals_bias;
10786 extern cvar_t cl_decals_models;
10787 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10788 // baseparms, parms, temps
10789 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)
10790 {
10791         int cornerindex;
10792         int index;
10793         float v[9][3];
10794         const float *vertex3f;
10795         const float *normal3f;
10796         int numpoints;
10797         float points[2][9][3];
10798         float temp[3];
10799         float tc[9][2];
10800         float f;
10801         float c[9][4];
10802         const int *e;
10803
10804         e = rsurface.modelelement3i + 3*triangleindex;
10805
10806         vertex3f = rsurface.modelvertex3f;
10807         normal3f = rsurface.modelnormal3f;
10808
10809         if (normal3f)
10810         {
10811                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10812                 {
10813                         index = 3*e[cornerindex];
10814                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10815                 }
10816         }
10817         else
10818         {
10819                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10820                 {
10821                         index = 3*e[cornerindex];
10822                         VectorCopy(vertex3f + index, v[cornerindex]);
10823                 }
10824         }
10825
10826         // cull backfaces
10827         //TriangleNormal(v[0], v[1], v[2], normal);
10828         //if (DotProduct(normal, localnormal) < 0.0f)
10829         //      continue;
10830         // clip by each of the box planes formed from the projection matrix
10831         // if anything survives, we emit the decal
10832         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]);
10833         if (numpoints < 3)
10834                 return;
10835         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]);
10836         if (numpoints < 3)
10837                 return;
10838         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]);
10839         if (numpoints < 3)
10840                 return;
10841         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]);
10842         if (numpoints < 3)
10843                 return;
10844         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]);
10845         if (numpoints < 3)
10846                 return;
10847         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]);
10848         if (numpoints < 3)
10849                 return;
10850         // some part of the triangle survived, so we have to accept it...
10851         if (dynamic)
10852         {
10853                 // dynamic always uses the original triangle
10854                 numpoints = 3;
10855                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10856                 {
10857                         index = 3*e[cornerindex];
10858                         VectorCopy(vertex3f + index, v[cornerindex]);
10859                 }
10860         }
10861         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10862         {
10863                 // convert vertex positions to texcoords
10864                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10865                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10866                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10867                 // calculate distance fade from the projection origin
10868                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10869                 f = bound(0.0f, f, 1.0f);
10870                 c[cornerindex][0] = r * f;
10871                 c[cornerindex][1] = g * f;
10872                 c[cornerindex][2] = b * f;
10873                 c[cornerindex][3] = 1.0f;
10874                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10875         }
10876         if (dynamic)
10877                 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);
10878         else
10879                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10880                         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);
10881 }
10882 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)
10883 {
10884         matrix4x4_t projection;
10885         decalsystem_t *decalsystem;
10886         qboolean dynamic;
10887         dp_model_t *model;
10888         const msurface_t *surface;
10889         const msurface_t *surfaces;
10890         const int *surfacelist;
10891         const texture_t *texture;
10892         int numtriangles;
10893         int numsurfacelist;
10894         int surfacelistindex;
10895         int surfaceindex;
10896         int triangleindex;
10897         float localorigin[3];
10898         float localnormal[3];
10899         float localmins[3];
10900         float localmaxs[3];
10901         float localsize;
10902         //float normal[3];
10903         float planes[6][4];
10904         float angles[3];
10905         bih_t *bih;
10906         int bih_triangles_count;
10907         int bih_triangles[256];
10908         int bih_surfaces[256];
10909
10910         decalsystem = &ent->decalsystem;
10911         model = ent->model;
10912         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10913         {
10914                 R_DecalSystem_Reset(&ent->decalsystem);
10915                 return;
10916         }
10917
10918         if (!model->brush.data_leafs && !cl_decals_models.integer)
10919         {
10920                 if (decalsystem->model)
10921                         R_DecalSystem_Reset(decalsystem);
10922                 return;
10923         }
10924
10925         if (decalsystem->model != model)
10926                 R_DecalSystem_Reset(decalsystem);
10927         decalsystem->model = model;
10928
10929         RSurf_ActiveModelEntity(ent, true, false, false);
10930
10931         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10932         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10933         VectorNormalize(localnormal);
10934         localsize = worldsize*rsurface.inversematrixscale;
10935         localmins[0] = localorigin[0] - localsize;
10936         localmins[1] = localorigin[1] - localsize;
10937         localmins[2] = localorigin[2] - localsize;
10938         localmaxs[0] = localorigin[0] + localsize;
10939         localmaxs[1] = localorigin[1] + localsize;
10940         localmaxs[2] = localorigin[2] + localsize;
10941
10942         //VectorCopy(localnormal, planes[4]);
10943         //VectorVectors(planes[4], planes[2], planes[0]);
10944         AnglesFromVectors(angles, localnormal, NULL, false);
10945         AngleVectors(angles, planes[0], planes[2], planes[4]);
10946         VectorNegate(planes[0], planes[1]);
10947         VectorNegate(planes[2], planes[3]);
10948         VectorNegate(planes[4], planes[5]);
10949         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10950         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10951         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10952         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10953         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10954         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10955
10956 #if 1
10957 // works
10958 {
10959         matrix4x4_t forwardprojection;
10960         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10961         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10962 }
10963 #else
10964 // broken
10965 {
10966         float projectionvector[4][3];
10967         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10968         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10969         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10970         projectionvector[0][0] = planes[0][0] * ilocalsize;
10971         projectionvector[0][1] = planes[1][0] * ilocalsize;
10972         projectionvector[0][2] = planes[2][0] * ilocalsize;
10973         projectionvector[1][0] = planes[0][1] * ilocalsize;
10974         projectionvector[1][1] = planes[1][1] * ilocalsize;
10975         projectionvector[1][2] = planes[2][1] * ilocalsize;
10976         projectionvector[2][0] = planes[0][2] * ilocalsize;
10977         projectionvector[2][1] = planes[1][2] * ilocalsize;
10978         projectionvector[2][2] = planes[2][2] * ilocalsize;
10979         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10980         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10981         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10982         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10983 }
10984 #endif
10985
10986         dynamic = model->surfmesh.isanimated;
10987         numsurfacelist = model->nummodelsurfaces;
10988         surfacelist = model->sortedmodelsurfaces;
10989         surfaces = model->data_surfaces;
10990
10991         bih = NULL;
10992         bih_triangles_count = -1;
10993         if(!dynamic)
10994         {
10995                 if(model->render_bih.numleafs)
10996                         bih = &model->render_bih;
10997                 else if(model->collision_bih.numleafs)
10998                         bih = &model->collision_bih;
10999         }
11000         if(bih)
11001                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11002         if(bih_triangles_count == 0)
11003                 return;
11004         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11005                 return;
11006         if(bih_triangles_count > 0)
11007         {
11008                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11009                 {
11010                         surfaceindex = bih_surfaces[triangleindex];
11011                         surface = surfaces + surfaceindex;
11012                         texture = surface->texture;
11013                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11014                                 continue;
11015                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11016                                 continue;
11017                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11018                 }
11019         }
11020         else
11021         {
11022                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11023                 {
11024                         surfaceindex = surfacelist[surfacelistindex];
11025                         surface = surfaces + surfaceindex;
11026                         // check cull box first because it rejects more than any other check
11027                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11028                                 continue;
11029                         // skip transparent surfaces
11030                         texture = surface->texture;
11031                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11032                                 continue;
11033                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11034                                 continue;
11035                         numtriangles = surface->num_triangles;
11036                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11037                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11038                 }
11039         }
11040 }
11041
11042 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11043 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)
11044 {
11045         int renderentityindex;
11046         float worldmins[3];
11047         float worldmaxs[3];
11048         entity_render_t *ent;
11049
11050         if (!cl_decals_newsystem.integer)
11051                 return;
11052
11053         worldmins[0] = worldorigin[0] - worldsize;
11054         worldmins[1] = worldorigin[1] - worldsize;
11055         worldmins[2] = worldorigin[2] - worldsize;
11056         worldmaxs[0] = worldorigin[0] + worldsize;
11057         worldmaxs[1] = worldorigin[1] + worldsize;
11058         worldmaxs[2] = worldorigin[2] + worldsize;
11059
11060         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11061
11062         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11063         {
11064                 ent = r_refdef.scene.entities[renderentityindex];
11065                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11066                         continue;
11067
11068                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11069         }
11070 }
11071
11072 typedef struct r_decalsystem_splatqueue_s
11073 {
11074         vec3_t worldorigin;
11075         vec3_t worldnormal;
11076         float color[4];
11077         float tcrange[4];
11078         float worldsize;
11079         int decalsequence;
11080 }
11081 r_decalsystem_splatqueue_t;
11082
11083 int r_decalsystem_numqueued = 0;
11084 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11085
11086 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)
11087 {
11088         r_decalsystem_splatqueue_t *queue;
11089
11090         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11091                 return;
11092
11093         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11094         VectorCopy(worldorigin, queue->worldorigin);
11095         VectorCopy(worldnormal, queue->worldnormal);
11096         Vector4Set(queue->color, r, g, b, a);
11097         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11098         queue->worldsize = worldsize;
11099         queue->decalsequence = cl.decalsequence++;
11100 }
11101
11102 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11103 {
11104         int i;
11105         r_decalsystem_splatqueue_t *queue;
11106
11107         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11108                 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);
11109         r_decalsystem_numqueued = 0;
11110 }
11111
11112 extern cvar_t cl_decals_max;
11113 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11114 {
11115         int i;
11116         decalsystem_t *decalsystem = &ent->decalsystem;
11117         int numdecals;
11118         int killsequence;
11119         tridecal_t *decal;
11120         float frametime;
11121         float lifetime;
11122
11123         if (!decalsystem->numdecals)
11124                 return;
11125
11126         if (r_showsurfaces.integer)
11127                 return;
11128
11129         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11130         {
11131                 R_DecalSystem_Reset(decalsystem);
11132                 return;
11133         }
11134
11135         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11136         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11137
11138         if (decalsystem->lastupdatetime)
11139                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11140         else
11141                 frametime = 0;
11142         decalsystem->lastupdatetime = r_refdef.scene.time;
11143         decal = decalsystem->decals;
11144         numdecals = decalsystem->numdecals;
11145
11146         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11147         {
11148                 if (decal->color4f[0][3])
11149                 {
11150                         decal->lived += frametime;
11151                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11152                         {
11153                                 memset(decal, 0, sizeof(*decal));
11154                                 if (decalsystem->freedecal > i)
11155                                         decalsystem->freedecal = i;
11156                         }
11157                 }
11158         }
11159         decal = decalsystem->decals;
11160         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11161                 numdecals--;
11162
11163         // collapse the array by shuffling the tail decals into the gaps
11164         for (;;)
11165         {
11166                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11167                         decalsystem->freedecal++;
11168                 if (decalsystem->freedecal == numdecals)
11169                         break;
11170                 decal[decalsystem->freedecal] = decal[--numdecals];
11171         }
11172
11173         decalsystem->numdecals = numdecals;
11174
11175         if (numdecals <= 0)
11176         {
11177                 // if there are no decals left, reset decalsystem
11178                 R_DecalSystem_Reset(decalsystem);
11179         }
11180 }
11181
11182 extern skinframe_t *decalskinframe;
11183 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11184 {
11185         int i;
11186         decalsystem_t *decalsystem = &ent->decalsystem;
11187         int numdecals;
11188         tridecal_t *decal;
11189         float faderate;
11190         float alpha;
11191         float *v3f;
11192         float *c4f;
11193         float *t2f;
11194         const int *e;
11195         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11196         int numtris = 0;
11197
11198         numdecals = decalsystem->numdecals;
11199         if (!numdecals)
11200                 return;
11201
11202         if (r_showsurfaces.integer)
11203                 return;
11204
11205         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11206         {
11207                 R_DecalSystem_Reset(decalsystem);
11208                 return;
11209         }
11210
11211         // if the model is static it doesn't matter what value we give for
11212         // wantnormals and wanttangents, so this logic uses only rules applicable
11213         // to a model, knowing that they are meaningless otherwise
11214         if (ent == r_refdef.scene.worldentity)
11215                 RSurf_ActiveWorldEntity();
11216         else
11217                 RSurf_ActiveModelEntity(ent, false, false, false);
11218
11219         decalsystem->lastupdatetime = r_refdef.scene.time;
11220         decal = decalsystem->decals;
11221
11222         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11223
11224         // update vertex positions for animated models
11225         v3f = decalsystem->vertex3f;
11226         c4f = decalsystem->color4f;
11227         t2f = decalsystem->texcoord2f;
11228         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11229         {
11230                 if (!decal->color4f[0][3])
11231                         continue;
11232
11233                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11234                         continue;
11235
11236                 // skip backfaces
11237                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11238                         continue;
11239
11240                 // update color values for fading decals
11241                 if (decal->lived >= cl_decals_time.value)
11242                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11243                 else
11244                         alpha = 1.0f;
11245
11246                 c4f[ 0] = decal->color4f[0][0] * alpha;
11247                 c4f[ 1] = decal->color4f[0][1] * alpha;
11248                 c4f[ 2] = decal->color4f[0][2] * alpha;
11249                 c4f[ 3] = 1;
11250                 c4f[ 4] = decal->color4f[1][0] * alpha;
11251                 c4f[ 5] = decal->color4f[1][1] * alpha;
11252                 c4f[ 6] = decal->color4f[1][2] * alpha;
11253                 c4f[ 7] = 1;
11254                 c4f[ 8] = decal->color4f[2][0] * alpha;
11255                 c4f[ 9] = decal->color4f[2][1] * alpha;
11256                 c4f[10] = decal->color4f[2][2] * alpha;
11257                 c4f[11] = 1;
11258
11259                 t2f[0] = decal->texcoord2f[0][0];
11260                 t2f[1] = decal->texcoord2f[0][1];
11261                 t2f[2] = decal->texcoord2f[1][0];
11262                 t2f[3] = decal->texcoord2f[1][1];
11263                 t2f[4] = decal->texcoord2f[2][0];
11264                 t2f[5] = decal->texcoord2f[2][1];
11265
11266                 // update vertex positions for animated models
11267                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11268                 {
11269                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11270                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11271                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11272                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11273                 }
11274                 else
11275                 {
11276                         VectorCopy(decal->vertex3f[0], v3f);
11277                         VectorCopy(decal->vertex3f[1], v3f + 3);
11278                         VectorCopy(decal->vertex3f[2], v3f + 6);
11279                 }
11280
11281                 if (r_refdef.fogenabled)
11282                 {
11283                         alpha = RSurf_FogVertex(v3f);
11284                         VectorScale(c4f, alpha, c4f);
11285                         alpha = RSurf_FogVertex(v3f + 3);
11286                         VectorScale(c4f + 4, alpha, c4f + 4);
11287                         alpha = RSurf_FogVertex(v3f + 6);
11288                         VectorScale(c4f + 8, alpha, c4f + 8);
11289                 }
11290
11291                 v3f += 9;
11292                 c4f += 12;
11293                 t2f += 6;
11294                 numtris++;
11295         }
11296
11297         if (numtris > 0)
11298         {
11299                 r_refdef.stats.drawndecals += numtris;
11300
11301                 // now render the decals all at once
11302                 // (this assumes they all use one particle font texture!)
11303                 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);
11304 //              R_Mesh_ResetTextureState();
11305                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11306                 GL_DepthMask(false);
11307                 GL_DepthRange(0, 1);
11308                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11309                 GL_DepthTest(true);
11310                 GL_CullFace(GL_NONE);
11311                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11312                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11313                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11314         }
11315 }
11316
11317 static void R_DrawModelDecals(void)
11318 {
11319         int i, numdecals;
11320
11321         // fade faster when there are too many decals
11322         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11323         for (i = 0;i < r_refdef.scene.numentities;i++)
11324                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11325
11326         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11327         for (i = 0;i < r_refdef.scene.numentities;i++)
11328                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11329                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11330
11331         R_DecalSystem_ApplySplatEntitiesQueue();
11332
11333         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11334         for (i = 0;i < r_refdef.scene.numentities;i++)
11335                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11336
11337         r_refdef.stats.totaldecals += numdecals;
11338
11339         if (r_showsurfaces.integer)
11340                 return;
11341
11342         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11343
11344         for (i = 0;i < r_refdef.scene.numentities;i++)
11345         {
11346                 if (!r_refdef.viewcache.entityvisible[i])
11347                         continue;
11348                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11349                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11350         }
11351 }
11352
11353 extern cvar_t mod_collision_bih;
11354 void R_DrawDebugModel(void)
11355 {
11356         entity_render_t *ent = rsurface.entity;
11357         int i, j, k, l, flagsmask;
11358         const msurface_t *surface;
11359         dp_model_t *model = ent->model;
11360         vec3_t v;
11361
11362         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11363                 return;
11364
11365         if (r_showoverdraw.value > 0)
11366         {
11367                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11368                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11369                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11370                 GL_DepthTest(false);
11371                 GL_DepthMask(false);
11372                 GL_DepthRange(0, 1);
11373                 GL_BlendFunc(GL_ONE, GL_ONE);
11374                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11375                 {
11376                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11377                                 continue;
11378                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11379                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11380                         {
11381                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11382                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11383                                 if (!rsurface.texture->currentlayers->depthmask)
11384                                         GL_Color(c, 0, 0, 1.0f);
11385                                 else if (ent == r_refdef.scene.worldentity)
11386                                         GL_Color(c, c, c, 1.0f);
11387                                 else
11388                                         GL_Color(0, c, 0, 1.0f);
11389                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11390                                 RSurf_DrawBatch();
11391                         }
11392                 }
11393                 rsurface.texture = NULL;
11394         }
11395
11396         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11397
11398 //      R_Mesh_ResetTextureState();
11399         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11400         GL_DepthRange(0, 1);
11401         GL_DepthTest(!r_showdisabledepthtest.integer);
11402         GL_DepthMask(false);
11403         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11404
11405         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11406         {
11407                 int triangleindex;
11408                 int bihleafindex;
11409                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11410                 const q3mbrush_t *brush;
11411                 const bih_t *bih = &model->collision_bih;
11412                 const bih_leaf_t *bihleaf;
11413                 float vertex3f[3][3];
11414                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11415                 cullbox = false;
11416                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11417                 {
11418                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11419                                 continue;
11420                         switch (bihleaf->type)
11421                         {
11422                         case BIH_BRUSH:
11423                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11424                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11425                                 {
11426                                         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);
11427                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11428                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11429                                 }
11430                                 break;
11431                         case BIH_COLLISIONTRIANGLE:
11432                                 triangleindex = bihleaf->itemindex;
11433                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11434                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11435                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11436                                 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);
11437                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11438                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11439                                 break;
11440                         case BIH_RENDERTRIANGLE:
11441                                 triangleindex = bihleaf->itemindex;
11442                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11443                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11444                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11445                                 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);
11446                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11447                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11448                                 break;
11449                         }
11450                 }
11451         }
11452
11453         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11454
11455 #ifndef USE_GLES2
11456         if (r_showtris.integer && qglPolygonMode)
11457         {
11458                 if (r_showdisabledepthtest.integer)
11459                 {
11460                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11461                         GL_DepthMask(false);
11462                 }
11463                 else
11464                 {
11465                         GL_BlendFunc(GL_ONE, GL_ZERO);
11466                         GL_DepthMask(true);
11467                 }
11468                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11469                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11470                 {
11471                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11472                                 continue;
11473                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11474                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11475                         {
11476                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11477                                 if (!rsurface.texture->currentlayers->depthmask)
11478                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11479                                 else if (ent == r_refdef.scene.worldentity)
11480                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11481                                 else
11482                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11483                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11484                                 RSurf_DrawBatch();
11485                         }
11486                 }
11487                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11488                 rsurface.texture = NULL;
11489         }
11490
11491         if (r_shownormals.value != 0 && qglBegin)
11492         {
11493                 if (r_showdisabledepthtest.integer)
11494                 {
11495                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11496                         GL_DepthMask(false);
11497                 }
11498                 else
11499                 {
11500                         GL_BlendFunc(GL_ONE, GL_ZERO);
11501                         GL_DepthMask(true);
11502                 }
11503                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11504                 {
11505                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11506                                 continue;
11507                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11508                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11509                         {
11510                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11511                                 qglBegin(GL_LINES);
11512                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11513                                 {
11514                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11515                                         {
11516                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11517                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11518                                                 qglVertex3f(v[0], v[1], v[2]);
11519                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11520                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11521                                                 qglVertex3f(v[0], v[1], v[2]);
11522                                         }
11523                                 }
11524                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11525                                 {
11526                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11527                                         {
11528                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11529                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11530                                                 qglVertex3f(v[0], v[1], v[2]);
11531                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11532                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11533                                                 qglVertex3f(v[0], v[1], v[2]);
11534                                         }
11535                                 }
11536                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11537                                 {
11538                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11539                                         {
11540                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11541                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11542                                                 qglVertex3f(v[0], v[1], v[2]);
11543                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11544                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11545                                                 qglVertex3f(v[0], v[1], v[2]);
11546                                         }
11547                                 }
11548                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11549                                 {
11550                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11551                                         {
11552                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11553                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11554                                                 qglVertex3f(v[0], v[1], v[2]);
11555                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11556                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11557                                                 qglVertex3f(v[0], v[1], v[2]);
11558                                         }
11559                                 }
11560                                 qglEnd();
11561                                 CHECKGLERROR
11562                         }
11563                 }
11564                 rsurface.texture = NULL;
11565         }
11566 #endif
11567 }
11568
11569 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11570 int r_maxsurfacelist = 0;
11571 const msurface_t **r_surfacelist = NULL;
11572 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11573 {
11574         int i, j, endj, flagsmask;
11575         dp_model_t *model = r_refdef.scene.worldmodel;
11576         msurface_t *surfaces;
11577         unsigned char *update;
11578         int numsurfacelist = 0;
11579         if (model == NULL)
11580                 return;
11581
11582         if (r_maxsurfacelist < model->num_surfaces)
11583         {
11584                 r_maxsurfacelist = model->num_surfaces;
11585                 if (r_surfacelist)
11586                         Mem_Free((msurface_t**)r_surfacelist);
11587                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11588         }
11589
11590         RSurf_ActiveWorldEntity();
11591
11592         surfaces = model->data_surfaces;
11593         update = model->brushq1.lightmapupdateflags;
11594
11595         // update light styles on this submodel
11596         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11597         {
11598                 model_brush_lightstyleinfo_t *style;
11599                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11600                 {
11601                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11602                         {
11603                                 int *list = style->surfacelist;
11604                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11605                                 for (j = 0;j < style->numsurfaces;j++)
11606                                         update[list[j]] = true;
11607                         }
11608                 }
11609         }
11610
11611         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11612
11613         if (debug)
11614         {
11615                 R_DrawDebugModel();
11616                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11617                 return;
11618         }
11619
11620         rsurface.lightmaptexture = NULL;
11621         rsurface.deluxemaptexture = NULL;
11622         rsurface.uselightmaptexture = false;
11623         rsurface.texture = NULL;
11624         rsurface.rtlight = NULL;
11625         numsurfacelist = 0;
11626         // add visible surfaces to draw list
11627         for (i = 0;i < model->nummodelsurfaces;i++)
11628         {
11629                 j = model->sortedmodelsurfaces[i];
11630                 if (r_refdef.viewcache.world_surfacevisible[j])
11631                         r_surfacelist[numsurfacelist++] = surfaces + j;
11632         }
11633         // update lightmaps if needed
11634         if (model->brushq1.firstrender)
11635         {
11636                 model->brushq1.firstrender = false;
11637                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11638                         if (update[j])
11639                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11640         }
11641         else if (update)
11642         {
11643                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11644                         if (r_refdef.viewcache.world_surfacevisible[j])
11645                                 if (update[j])
11646                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11647         }
11648         // don't do anything if there were no surfaces
11649         if (!numsurfacelist)
11650         {
11651                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11652                 return;
11653         }
11654         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11655
11656         // add to stats if desired
11657         if (r_speeds.integer && !skysurfaces && !depthonly)
11658         {
11659                 r_refdef.stats.world_surfaces += numsurfacelist;
11660                 for (j = 0;j < numsurfacelist;j++)
11661                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11662         }
11663
11664         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11665 }
11666
11667 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11668 {
11669         int i, j, endj, flagsmask;
11670         dp_model_t *model = ent->model;
11671         msurface_t *surfaces;
11672         unsigned char *update;
11673         int numsurfacelist = 0;
11674         if (model == NULL)
11675                 return;
11676
11677         if (r_maxsurfacelist < model->num_surfaces)
11678         {
11679                 r_maxsurfacelist = model->num_surfaces;
11680                 if (r_surfacelist)
11681                         Mem_Free((msurface_t **)r_surfacelist);
11682                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11683         }
11684
11685         // if the model is static it doesn't matter what value we give for
11686         // wantnormals and wanttangents, so this logic uses only rules applicable
11687         // to a model, knowing that they are meaningless otherwise
11688         if (ent == r_refdef.scene.worldentity)
11689                 RSurf_ActiveWorldEntity();
11690         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11691                 RSurf_ActiveModelEntity(ent, false, false, false);
11692         else if (prepass)
11693                 RSurf_ActiveModelEntity(ent, true, true, true);
11694         else if (depthonly)
11695         {
11696                 switch (vid.renderpath)
11697                 {
11698                 case RENDERPATH_GL20:
11699                 case RENDERPATH_D3D9:
11700                 case RENDERPATH_D3D10:
11701                 case RENDERPATH_D3D11:
11702                 case RENDERPATH_SOFT:
11703                 case RENDERPATH_GLES2:
11704                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11705                         break;
11706                 case RENDERPATH_GL11:
11707                 case RENDERPATH_GL13:
11708                 case RENDERPATH_GLES1:
11709                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11710                         break;
11711                 }
11712         }
11713         else
11714         {
11715                 switch (vid.renderpath)
11716                 {
11717                 case RENDERPATH_GL20:
11718                 case RENDERPATH_D3D9:
11719                 case RENDERPATH_D3D10:
11720                 case RENDERPATH_D3D11:
11721                 case RENDERPATH_SOFT:
11722                 case RENDERPATH_GLES2:
11723                         RSurf_ActiveModelEntity(ent, true, true, false);
11724                         break;
11725                 case RENDERPATH_GL11:
11726                 case RENDERPATH_GL13:
11727                 case RENDERPATH_GLES1:
11728                         RSurf_ActiveModelEntity(ent, true, false, false);
11729                         break;
11730                 }
11731         }
11732
11733         surfaces = model->data_surfaces;
11734         update = model->brushq1.lightmapupdateflags;
11735
11736         // update light styles
11737         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11738         {
11739                 model_brush_lightstyleinfo_t *style;
11740                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11741                 {
11742                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11743                         {
11744                                 int *list = style->surfacelist;
11745                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11746                                 for (j = 0;j < style->numsurfaces;j++)
11747                                         update[list[j]] = true;
11748                         }
11749                 }
11750         }
11751
11752         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11753
11754         if (debug)
11755         {
11756                 R_DrawDebugModel();
11757                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11758                 return;
11759         }
11760
11761         rsurface.lightmaptexture = NULL;
11762         rsurface.deluxemaptexture = NULL;
11763         rsurface.uselightmaptexture = false;
11764         rsurface.texture = NULL;
11765         rsurface.rtlight = NULL;
11766         numsurfacelist = 0;
11767         // add visible surfaces to draw list
11768         for (i = 0;i < model->nummodelsurfaces;i++)
11769                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11770         // don't do anything if there were no surfaces
11771         if (!numsurfacelist)
11772         {
11773                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11774                 return;
11775         }
11776         // update lightmaps if needed
11777         if (update)
11778         {
11779                 int updated = 0;
11780                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11781                 {
11782                         if (update[j])
11783                         {
11784                                 updated++;
11785                                 R_BuildLightMap(ent, surfaces + j);
11786                         }
11787                 }
11788         }
11789         if (update)
11790                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11791                         if (update[j])
11792                                 R_BuildLightMap(ent, surfaces + j);
11793         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11794
11795         // add to stats if desired
11796         if (r_speeds.integer && !skysurfaces && !depthonly)
11797         {
11798                 r_refdef.stats.entities_surfaces += numsurfacelist;
11799                 for (j = 0;j < numsurfacelist;j++)
11800                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11801         }
11802
11803         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11804 }
11805
11806 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11807 {
11808         static texture_t texture;
11809         static msurface_t surface;
11810         const msurface_t *surfacelist = &surface;
11811
11812         // fake enough texture and surface state to render this geometry
11813
11814         texture.update_lastrenderframe = -1; // regenerate this texture
11815         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11816         texture.currentskinframe = skinframe;
11817         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11818         texture.offsetmapping = OFFSETMAPPING_OFF;
11819         texture.offsetscale = 1;
11820         texture.specularscalemod = 1;
11821         texture.specularpowermod = 1;
11822
11823         surface.texture = &texture;
11824         surface.num_triangles = numtriangles;
11825         surface.num_firsttriangle = firsttriangle;
11826         surface.num_vertices = numvertices;
11827         surface.num_firstvertex = firstvertex;
11828
11829         // now render it
11830         rsurface.texture = R_GetCurrentTexture(surface.texture);
11831         rsurface.lightmaptexture = NULL;
11832         rsurface.deluxemaptexture = NULL;
11833         rsurface.uselightmaptexture = false;
11834         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11835 }
11836
11837 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)
11838 {
11839         static msurface_t surface;
11840         const msurface_t *surfacelist = &surface;
11841
11842         // fake enough texture and surface state to render this geometry
11843         surface.texture = texture;
11844         surface.num_triangles = numtriangles;
11845         surface.num_firsttriangle = firsttriangle;
11846         surface.num_vertices = numvertices;
11847         surface.num_firstvertex = firstvertex;
11848
11849         // now render it
11850         rsurface.texture = R_GetCurrentTexture(surface.texture);
11851         rsurface.lightmaptexture = NULL;
11852         rsurface.deluxemaptexture = NULL;
11853         rsurface.uselightmaptexture = false;
11854         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11855 }