]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix compile errors in D3D renderer (missing vabuf variable)
[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_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142
143 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)"};
144 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"};
145
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149
150 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"};
151 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"};
152 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
153 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
154 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"};
155 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)"};
156 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)"};
157 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158
159 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)"};
160 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
161 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)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
163 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)"};
164 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)"};
165 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
166 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"};
167 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."};
168 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176 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)"};
177
178 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)"};
179 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
180 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"};
181 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
182 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
183 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 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"};
185 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
186 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
187
188 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
189 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
190 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
191 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
192
193 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
194 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
195
196 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
197 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
198 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
199 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
200 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
201
202 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
203 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
204 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
205 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
206 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
208 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
209 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
210 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
211 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
212
213 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"};
214
215 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"};
216
217 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
218
219 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
220
221 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
222 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"};
223
224 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."};
225
226 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)"};
227
228 extern cvar_t v_glslgamma;
229 extern cvar_t v_glslgamma_2d;
230
231 extern qboolean v_flipped_state;
232
233 r_framebufferstate_t r_fb;
234
235 /// shadow volume bsp struct with automatically growing nodes buffer
236 svbsp_t r_svbsp;
237
238 rtexture_t *r_texture_blanknormalmap;
239 rtexture_t *r_texture_white;
240 rtexture_t *r_texture_grey128;
241 rtexture_t *r_texture_black;
242 rtexture_t *r_texture_notexture;
243 rtexture_t *r_texture_whitecube;
244 rtexture_t *r_texture_normalizationcube;
245 rtexture_t *r_texture_fogattenuation;
246 rtexture_t *r_texture_fogheighttexture;
247 rtexture_t *r_texture_gammaramps;
248 unsigned int r_texture_gammaramps_serial;
249 //rtexture_t *r_texture_fogintensity;
250 rtexture_t *r_texture_reflectcube;
251
252 // TODO: hash lookups?
253 typedef struct cubemapinfo_s
254 {
255         char basename[64];
256         rtexture_t *texture;
257 }
258 cubemapinfo_t;
259
260 int r_texture_numcubemaps;
261 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
262
263 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
264 unsigned int r_numqueries;
265 unsigned int r_maxqueries;
266
267 typedef struct r_qwskincache_s
268 {
269         char name[MAX_QPATH];
270         skinframe_t *skinframe;
271 }
272 r_qwskincache_t;
273
274 static r_qwskincache_t *r_qwskincache;
275 static int r_qwskincache_size;
276
277 /// vertex coordinates for a quad that covers the screen exactly
278 extern const float r_screenvertex3f[12];
279 extern const float r_d3dscreenvertex3f[12];
280 const float r_screenvertex3f[12] =
281 {
282         0, 0, 0,
283         1, 0, 0,
284         1, 1, 0,
285         0, 1, 0
286 };
287 const float r_d3dscreenvertex3f[12] =
288 {
289         0, 1, 0,
290         1, 1, 0,
291         1, 0, 0,
292         0, 0, 0
293 };
294
295 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
296 {
297         int i;
298         for (i = 0;i < verts;i++)
299         {
300                 out[0] = in[0] * r;
301                 out[1] = in[1] * g;
302                 out[2] = in[2] * b;
303                 out[3] = in[3];
304                 in += 4;
305                 out += 4;
306         }
307 }
308
309 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
310 {
311         int i;
312         for (i = 0;i < verts;i++)
313         {
314                 out[0] = r;
315                 out[1] = g;
316                 out[2] = b;
317                 out[3] = a;
318                 out += 4;
319         }
320 }
321
322 // FIXME: move this to client?
323 void FOG_clear(void)
324 {
325         if (gamemode == GAME_NEHAHRA)
326         {
327                 Cvar_Set("gl_fogenable", "0");
328                 Cvar_Set("gl_fogdensity", "0.2");
329                 Cvar_Set("gl_fogred", "0.3");
330                 Cvar_Set("gl_foggreen", "0.3");
331                 Cvar_Set("gl_fogblue", "0.3");
332         }
333         r_refdef.fog_density = 0;
334         r_refdef.fog_red = 0;
335         r_refdef.fog_green = 0;
336         r_refdef.fog_blue = 0;
337         r_refdef.fog_alpha = 1;
338         r_refdef.fog_start = 0;
339         r_refdef.fog_end = 16384;
340         r_refdef.fog_height = 1<<30;
341         r_refdef.fog_fadedepth = 128;
342         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
343 }
344
345 static void R_BuildBlankTextures(void)
346 {
347         unsigned char data[4];
348         data[2] = 128; // normal X
349         data[1] = 128; // normal Y
350         data[0] = 255; // normal Z
351         data[3] = 255; // height
352         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353         data[0] = 255;
354         data[1] = 255;
355         data[2] = 255;
356         data[3] = 255;
357         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 128;
359         data[1] = 128;
360         data[2] = 128;
361         data[3] = 255;
362         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 0;
364         data[1] = 0;
365         data[2] = 0;
366         data[3] = 255;
367         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368 }
369
370 static void R_BuildNoTexture(void)
371 {
372         int x, y;
373         unsigned char pix[16][16][4];
374         // this makes a light grey/dark grey checkerboard texture
375         for (y = 0;y < 16;y++)
376         {
377                 for (x = 0;x < 16;x++)
378                 {
379                         if ((y < 8) ^ (x < 8))
380                         {
381                                 pix[y][x][0] = 128;
382                                 pix[y][x][1] = 128;
383                                 pix[y][x][2] = 128;
384                                 pix[y][x][3] = 255;
385                         }
386                         else
387                         {
388                                 pix[y][x][0] = 64;
389                                 pix[y][x][1] = 64;
390                                 pix[y][x][2] = 64;
391                                 pix[y][x][3] = 255;
392                         }
393                 }
394         }
395         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildWhiteCube(void)
399 {
400         unsigned char data[6*1*1*4];
401         memset(data, 255, sizeof(data));
402         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNormalizationCube(void)
406 {
407         int x, y, side;
408         vec3_t v;
409         vec_t s, t, intensity;
410 #define NORMSIZE 64
411         unsigned char *data;
412         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
413         for (side = 0;side < 6;side++)
414         {
415                 for (y = 0;y < NORMSIZE;y++)
416                 {
417                         for (x = 0;x < NORMSIZE;x++)
418                         {
419                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
420                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
421                                 switch(side)
422                                 {
423                                 default:
424                                 case 0:
425                                         v[0] = 1;
426                                         v[1] = -t;
427                                         v[2] = -s;
428                                         break;
429                                 case 1:
430                                         v[0] = -1;
431                                         v[1] = -t;
432                                         v[2] = s;
433                                         break;
434                                 case 2:
435                                         v[0] = s;
436                                         v[1] = 1;
437                                         v[2] = t;
438                                         break;
439                                 case 3:
440                                         v[0] = s;
441                                         v[1] = -1;
442                                         v[2] = -t;
443                                         break;
444                                 case 4:
445                                         v[0] = s;
446                                         v[1] = -t;
447                                         v[2] = 1;
448                                         break;
449                                 case 5:
450                                         v[0] = -s;
451                                         v[1] = -t;
452                                         v[2] = -1;
453                                         break;
454                                 }
455                                 intensity = 127.0f / sqrt(DotProduct(v, v));
456                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
457                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
458                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
459                                 data[((side*64+y)*64+x)*4+3] = 255;
460                         }
461                 }
462         }
463         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
464         Mem_Free(data);
465 }
466
467 static void R_BuildFogTexture(void)
468 {
469         int x, b;
470 #define FOGWIDTH 256
471         unsigned char data1[FOGWIDTH][4];
472         //unsigned char data2[FOGWIDTH][4];
473         double d, r, alpha;
474
475         r_refdef.fogmasktable_start = r_refdef.fog_start;
476         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
477         r_refdef.fogmasktable_range = r_refdef.fogrange;
478         r_refdef.fogmasktable_density = r_refdef.fog_density;
479
480         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
481         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
482         {
483                 d = (x * r - r_refdef.fogmasktable_start);
484                 if(developer_extra.integer)
485                         Con_DPrintf("%f ", d);
486                 d = max(0, d);
487                 if (r_fog_exp2.integer)
488                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
489                 else
490                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
491                 if(developer_extra.integer)
492                         Con_DPrintf(" : %f ", alpha);
493                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
494                 if(developer_extra.integer)
495                         Con_DPrintf(" = %f\n", alpha);
496                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
497         }
498
499         for (x = 0;x < FOGWIDTH;x++)
500         {
501                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
502                 data1[x][0] = b;
503                 data1[x][1] = b;
504                 data1[x][2] = b;
505                 data1[x][3] = 255;
506                 //data2[x][0] = 255 - b;
507                 //data2[x][1] = 255 - b;
508                 //data2[x][2] = 255 - b;
509                 //data2[x][3] = 255;
510         }
511         if (r_texture_fogattenuation)
512         {
513                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
514                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
515         }
516         else
517         {
518                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
519                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
520         }
521 }
522
523 static void R_BuildFogHeightTexture(void)
524 {
525         unsigned char *inpixels;
526         int size;
527         int x;
528         int y;
529         int j;
530         float c[4];
531         float f;
532         inpixels = NULL;
533         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
534         if (r_refdef.fogheighttexturename[0])
535                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
536         if (!inpixels)
537         {
538                 r_refdef.fog_height_tablesize = 0;
539                 if (r_texture_fogheighttexture)
540                         R_FreeTexture(r_texture_fogheighttexture);
541                 r_texture_fogheighttexture = NULL;
542                 if (r_refdef.fog_height_table2d)
543                         Mem_Free(r_refdef.fog_height_table2d);
544                 r_refdef.fog_height_table2d = NULL;
545                 if (r_refdef.fog_height_table1d)
546                         Mem_Free(r_refdef.fog_height_table1d);
547                 r_refdef.fog_height_table1d = NULL;
548                 return;
549         }
550         size = image_width;
551         r_refdef.fog_height_tablesize = size;
552         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
553         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
554         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
555         Mem_Free(inpixels);
556         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
557         // average fog color table accounting for every fog layer between a point
558         // and the camera.  (Note: attenuation is handled separately!)
559         for (y = 0;y < size;y++)
560         {
561                 for (x = 0;x < size;x++)
562                 {
563                         Vector4Clear(c);
564                         f = 0;
565                         if (x < y)
566                         {
567                                 for (j = x;j <= y;j++)
568                                 {
569                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
570                                         f++;
571                                 }
572                         }
573                         else
574                         {
575                                 for (j = x;j >= y;j--)
576                                 {
577                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
578                                         f++;
579                                 }
580                         }
581                         f = 1.0f / f;
582                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
583                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
584                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
586                 }
587         }
588         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
589 }
590
591 //=======================================================================================================================================================
592
593 static const char *builtinshaderstring =
594 #include "shader_glsl.h"
595 ;
596
597 const char *builtinhlslshaderstring =
598 #include "shader_hlsl.h"
599 ;
600
601 char *glslshaderstring = NULL;
602 char *hlslshaderstring = NULL;
603
604 //=======================================================================================================================================================
605
606 typedef struct shaderpermutationinfo_s
607 {
608         const char *pretext;
609         const char *name;
610 }
611 shaderpermutationinfo_t;
612
613 typedef struct shadermodeinfo_s
614 {
615         const char *vertexfilename;
616         const char *geometryfilename;
617         const char *fragmentfilename;
618         const char *pretext;
619         const char *name;
620 }
621 shadermodeinfo_t;
622
623 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
624 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
625 {
626         {"#define USEDIFFUSE\n", " diffuse"},
627         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
628         {"#define USEVIEWTINT\n", " viewtint"},
629         {"#define USECOLORMAPPING\n", " colormapping"},
630         {"#define USESATURATION\n", " saturation"},
631         {"#define USEFOGINSIDE\n", " foginside"},
632         {"#define USEFOGOUTSIDE\n", " fogoutside"},
633         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
634         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
635         {"#define USEGAMMARAMPS\n", " gammaramps"},
636         {"#define USECUBEFILTER\n", " cubefilter"},
637         {"#define USEGLOW\n", " glow"},
638         {"#define USEBLOOM\n", " bloom"},
639         {"#define USESPECULAR\n", " specular"},
640         {"#define USEPOSTPROCESSING\n", " postprocessing"},
641         {"#define USEREFLECTION\n", " reflection"},
642         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
643         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
644         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
645         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
646         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
647         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
656         {"#define USETRIPPY\n", " trippy"},
657 };
658
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
680 };
681
682 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 };
703
704 struct r_glsl_permutation_s;
705 typedef struct r_glsl_permutation_s
706 {
707         /// hash lookup data
708         struct r_glsl_permutation_s *hashnext;
709         unsigned int mode;
710         unsigned int permutation;
711
712         /// indicates if we have tried compiling this permutation already
713         qboolean compiled;
714         /// 0 if compilation failed
715         int program;
716         // texture units assigned to each detected uniform
717         int tex_Texture_First;
718         int tex_Texture_Second;
719         int tex_Texture_GammaRamps;
720         int tex_Texture_Normal;
721         int tex_Texture_Color;
722         int tex_Texture_Gloss;
723         int tex_Texture_Glow;
724         int tex_Texture_SecondaryNormal;
725         int tex_Texture_SecondaryColor;
726         int tex_Texture_SecondaryGloss;
727         int tex_Texture_SecondaryGlow;
728         int tex_Texture_Pants;
729         int tex_Texture_Shirt;
730         int tex_Texture_FogHeightTexture;
731         int tex_Texture_FogMask;
732         int tex_Texture_Lightmap;
733         int tex_Texture_Deluxemap;
734         int tex_Texture_Attenuation;
735         int tex_Texture_Cube;
736         int tex_Texture_Refraction;
737         int tex_Texture_Reflection;
738         int tex_Texture_ShadowMap2D;
739         int tex_Texture_CubeProjection;
740         int tex_Texture_ScreenDepth;
741         int tex_Texture_ScreenNormalMap;
742         int tex_Texture_ScreenDiffuse;
743         int tex_Texture_ScreenSpecular;
744         int tex_Texture_ReflectMask;
745         int tex_Texture_ReflectCube;
746         int tex_Texture_BounceGrid;
747         /// locations of detected uniforms in program object, or -1 if not found
748         int loc_Texture_First;
749         int loc_Texture_Second;
750         int loc_Texture_GammaRamps;
751         int loc_Texture_Normal;
752         int loc_Texture_Color;
753         int loc_Texture_Gloss;
754         int loc_Texture_Glow;
755         int loc_Texture_SecondaryNormal;
756         int loc_Texture_SecondaryColor;
757         int loc_Texture_SecondaryGloss;
758         int loc_Texture_SecondaryGlow;
759         int loc_Texture_Pants;
760         int loc_Texture_Shirt;
761         int loc_Texture_FogHeightTexture;
762         int loc_Texture_FogMask;
763         int loc_Texture_Lightmap;
764         int loc_Texture_Deluxemap;
765         int loc_Texture_Attenuation;
766         int loc_Texture_Cube;
767         int loc_Texture_Refraction;
768         int loc_Texture_Reflection;
769         int loc_Texture_ShadowMap2D;
770         int loc_Texture_CubeProjection;
771         int loc_Texture_ScreenDepth;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_OffsetMapping_LodDistance;
804         int loc_OffsetMapping_Bias;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
852         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
853 };
854 #define SHADERSTATICPARMS_COUNT 8
855
856 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
857 static int shaderstaticparms_count = 0;
858
859 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
860 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
861 static qboolean R_CompileShader_CheckStaticParms(void)
862 {
863         static int r_compileshader_staticparms_save[1];
864         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
865         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
866
867         // detect all
868         if (r_glsl_saturation_redcompensate.integer)
869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
870         if (r_glsl_vertextextureblend_usebothalphas.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
872         if (r_shadow_glossexact.integer)
873                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
874         if (r_glsl_postprocess.integer)
875         {
876                 if (r_glsl_postprocess_uservec1_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
878                 if (r_glsl_postprocess_uservec2_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
880                 if (r_glsl_postprocess_uservec3_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
882                 if (r_glsl_postprocess_uservec4_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
884         }
885         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
887         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
888 }
889
890 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
891         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
892                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
893         else \
894                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
895 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
896 {
897         shaderstaticparms_count = 0;
898
899         // emit all
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
908 }
909
910 /// information about each possible shader permutation
911 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
912 /// currently selected permutation
913 r_glsl_permutation_t *r_glsl_permutation;
914 /// storage for permutations linked in the hash table
915 memexpandablearray_t r_glsl_permutationarray;
916
917 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
918 {
919         //unsigned int hashdepth = 0;
920         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
921         r_glsl_permutation_t *p;
922         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
923         {
924                 if (p->mode == mode && p->permutation == permutation)
925                 {
926                         //if (hashdepth > 10)
927                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928                         return p;
929                 }
930                 //hashdepth++;
931         }
932         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
933         p->mode = mode;
934         p->permutation = permutation;
935         p->hashnext = r_glsl_permutationhash[mode][hashindex];
936         r_glsl_permutationhash[mode][hashindex] = p;
937         //if (hashdepth > 10)
938         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
939         return p;
940 }
941
942 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
943 {
944         char *shaderstring;
945         if (!filename || !filename[0])
946                 return NULL;
947         if (!strcmp(filename, "glsl/default.glsl"))
948         {
949                 if (!glslshaderstring)
950                 {
951                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
952                         if (glslshaderstring)
953                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
954                         else
955                                 glslshaderstring = (char *)builtinshaderstring;
956                 }
957                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
958                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
959                 return shaderstring;
960         }
961         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
962         if (shaderstring)
963         {
964                 if (printfromdisknotice)
965                         Con_DPrintf("from disk %s... ", filename);
966                 return shaderstring;
967         }
968         return shaderstring;
969 }
970
971 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
972 {
973         int i;
974         int sampler;
975         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
976         char *vertexstring, *geometrystring, *fragmentstring;
977         char permutationname[256];
978         int vertstrings_count = 0;
979         int geomstrings_count = 0;
980         int fragstrings_count = 0;
981         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
982         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
983         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
984
985         if (p->compiled)
986                 return;
987         p->compiled = true;
988         p->program = 0;
989
990         permutationname[0] = 0;
991         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
992         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
993         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
994
995         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
996
997         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
998         if(vid.support.gl20shaders130)
999         {
1000                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1001                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1002                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1003                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1004                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1005                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1006         }
1007
1008         // the first pretext is which type of shader to compile as
1009         // (later these will all be bound together as a program object)
1010         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1011         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1012         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1013
1014         // the second pretext is the mode (for example a light source)
1015         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1016         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1017         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1018         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1019
1020         // now add all the permutation pretexts
1021         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1022         {
1023                 if (permutation & (1<<i))
1024                 {
1025                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1027                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1028                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1029                 }
1030                 else
1031                 {
1032                         // keep line numbers correct
1033                         vertstrings_list[vertstrings_count++] = "\n";
1034                         geomstrings_list[geomstrings_count++] = "\n";
1035                         fragstrings_list[fragstrings_count++] = "\n";
1036                 }
1037         }
1038
1039         // add static parms
1040         R_CompileShader_AddStaticParms(mode, permutation);
1041         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         vertstrings_count += shaderstaticparms_count;
1043         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1044         geomstrings_count += shaderstaticparms_count;
1045         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1046         fragstrings_count += shaderstaticparms_count;
1047
1048         // now append the shader text itself
1049         vertstrings_list[vertstrings_count++] = vertexstring;
1050         geomstrings_list[geomstrings_count++] = geometrystring;
1051         fragstrings_list[fragstrings_count++] = fragmentstring;
1052
1053         // if any sources were NULL, clear the respective list
1054         if (!vertexstring)
1055                 vertstrings_count = 0;
1056         if (!geometrystring)
1057                 geomstrings_count = 0;
1058         if (!fragmentstring)
1059                 fragstrings_count = 0;
1060
1061         // compile the shader program
1062         if (vertstrings_count + geomstrings_count + fragstrings_count)
1063                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1064         if (p->program)
1065         {
1066                 CHECKGLERROR
1067                 qglUseProgram(p->program);CHECKGLERROR
1068                 // look up all the uniform variable names we care about, so we don't
1069                 // have to look them up every time we set them
1070
1071                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1072                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1073                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1074                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1075                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1076                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1077                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1078                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1079                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1080                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1081                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1082                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1083                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1084                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1085                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1086                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1087                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1088                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1089                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1090                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1091                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1092                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1093                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1094                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1095                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1096                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1097                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1098                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1099                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1100                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1101                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1102                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1103                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1104                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1105                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1106                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1107                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1108                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1109                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1110                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1111                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1112                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1113                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1114                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1115                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1116                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1117                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1118                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1119                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1120                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1121                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1122                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1123                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1124                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1125                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1126                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1127                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1128                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1129                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1130                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1131                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1132                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1133                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1134                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1135                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1136                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1137                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1138                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1139                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1140                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1141                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1142                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1143                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1144                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1145                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1146                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1147                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1148                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1149                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1150                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1151                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1152                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1153                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1154                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1155                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1156                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1157                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1158                 // initialize the samplers to refer to the texture units we use
1159                 p->tex_Texture_First = -1;
1160                 p->tex_Texture_Second = -1;
1161                 p->tex_Texture_GammaRamps = -1;
1162                 p->tex_Texture_Normal = -1;
1163                 p->tex_Texture_Color = -1;
1164                 p->tex_Texture_Gloss = -1;
1165                 p->tex_Texture_Glow = -1;
1166                 p->tex_Texture_SecondaryNormal = -1;
1167                 p->tex_Texture_SecondaryColor = -1;
1168                 p->tex_Texture_SecondaryGloss = -1;
1169                 p->tex_Texture_SecondaryGlow = -1;
1170                 p->tex_Texture_Pants = -1;
1171                 p->tex_Texture_Shirt = -1;
1172                 p->tex_Texture_FogHeightTexture = -1;
1173                 p->tex_Texture_FogMask = -1;
1174                 p->tex_Texture_Lightmap = -1;
1175                 p->tex_Texture_Deluxemap = -1;
1176                 p->tex_Texture_Attenuation = -1;
1177                 p->tex_Texture_Cube = -1;
1178                 p->tex_Texture_Refraction = -1;
1179                 p->tex_Texture_Reflection = -1;
1180                 p->tex_Texture_ShadowMap2D = -1;
1181                 p->tex_Texture_CubeProjection = -1;
1182                 p->tex_Texture_ScreenDepth = -1;
1183                 p->tex_Texture_ScreenNormalMap = -1;
1184                 p->tex_Texture_ScreenDiffuse = -1;
1185                 p->tex_Texture_ScreenSpecular = -1;
1186                 p->tex_Texture_ReflectMask = -1;
1187                 p->tex_Texture_ReflectCube = -1;
1188                 p->tex_Texture_BounceGrid = -1;
1189                 sampler = 0;
1190                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1191                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1192                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1193                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1194                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1195                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1196                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1199                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1200                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1201                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1202                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1203                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1204                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1205                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1206                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1207                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1208                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1209                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1210                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1211                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1212                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1215                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1216                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1217                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1218                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1219                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1220                 CHECKGLERROR
1221                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1222         }
1223         else
1224                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1225
1226         // free the strings
1227         if (vertexstring)
1228                 Mem_Free(vertexstring);
1229         if (geometrystring)
1230                 Mem_Free(geometrystring);
1231         if (fragmentstring)
1232                 Mem_Free(fragmentstring);
1233 }
1234
1235 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1236 {
1237         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1238         if (r_glsl_permutation != perm)
1239         {
1240                 r_glsl_permutation = perm;
1241                 if (!r_glsl_permutation->program)
1242                 {
1243                         if (!r_glsl_permutation->compiled)
1244                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1245                         if (!r_glsl_permutation->program)
1246                         {
1247                                 // remove features until we find a valid permutation
1248                                 int i;
1249                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1250                                 {
1251                                         // reduce i more quickly whenever it would not remove any bits
1252                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1253                                         if (!(permutation & j))
1254                                                 continue;
1255                                         permutation -= j;
1256                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1257                                         if (!r_glsl_permutation->compiled)
1258                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                                         if (r_glsl_permutation->program)
1260                                                 break;
1261                                 }
1262                                 if (i >= SHADERPERMUTATION_COUNT)
1263                                 {
1264                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1265                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1266                                         qglUseProgram(0);CHECKGLERROR
1267                                         return; // no bit left to clear, entire mode is broken
1268                                 }
1269                         }
1270                 }
1271                 CHECKGLERROR
1272                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1273         }
1274         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1275         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1276         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1277 }
1278
1279 #ifdef SUPPORTD3D
1280
1281 #ifdef SUPPORTD3D
1282 #include <d3d9.h>
1283 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1284 extern D3DCAPS9 vid_d3d9caps;
1285 #endif
1286
1287 struct r_hlsl_permutation_s;
1288 typedef struct r_hlsl_permutation_s
1289 {
1290         /// hash lookup data
1291         struct r_hlsl_permutation_s *hashnext;
1292         unsigned int mode;
1293         unsigned int permutation;
1294
1295         /// indicates if we have tried compiling this permutation already
1296         qboolean compiled;
1297         /// NULL if compilation failed
1298         IDirect3DVertexShader9 *vertexshader;
1299         IDirect3DPixelShader9 *pixelshader;
1300 }
1301 r_hlsl_permutation_t;
1302
1303 typedef enum D3DVSREGISTER_e
1304 {
1305         D3DVSREGISTER_TexMatrix = 0, // float4x4
1306         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1307         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1308         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1309         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1310         D3DVSREGISTER_ModelToLight = 20, // float4x4
1311         D3DVSREGISTER_EyePosition = 24,
1312         D3DVSREGISTER_FogPlane = 25,
1313         D3DVSREGISTER_LightDir = 26,
1314         D3DVSREGISTER_LightPosition = 27,
1315 }
1316 D3DVSREGISTER_t;
1317
1318 typedef enum D3DPSREGISTER_e
1319 {
1320         D3DPSREGISTER_Alpha = 0,
1321         D3DPSREGISTER_BloomBlur_Parameters = 1,
1322         D3DPSREGISTER_ClientTime = 2,
1323         D3DPSREGISTER_Color_Ambient = 3,
1324         D3DPSREGISTER_Color_Diffuse = 4,
1325         D3DPSREGISTER_Color_Specular = 5,
1326         D3DPSREGISTER_Color_Glow = 6,
1327         D3DPSREGISTER_Color_Pants = 7,
1328         D3DPSREGISTER_Color_Shirt = 8,
1329         D3DPSREGISTER_DeferredColor_Ambient = 9,
1330         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1331         D3DPSREGISTER_DeferredColor_Specular = 11,
1332         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1333         D3DPSREGISTER_DeferredMod_Specular = 13,
1334         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1335         D3DPSREGISTER_EyePosition = 15, // unused
1336         D3DPSREGISTER_FogColor = 16,
1337         D3DPSREGISTER_FogHeightFade = 17,
1338         D3DPSREGISTER_FogPlane = 18,
1339         D3DPSREGISTER_FogPlaneViewDist = 19,
1340         D3DPSREGISTER_FogRangeRecip = 20,
1341         D3DPSREGISTER_LightColor = 21,
1342         D3DPSREGISTER_LightDir = 22, // unused
1343         D3DPSREGISTER_LightPosition = 23,
1344         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1345         D3DPSREGISTER_PixelSize = 25,
1346         D3DPSREGISTER_ReflectColor = 26,
1347         D3DPSREGISTER_ReflectFactor = 27,
1348         D3DPSREGISTER_ReflectOffset = 28,
1349         D3DPSREGISTER_RefractColor = 29,
1350         D3DPSREGISTER_Saturation = 30,
1351         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1352         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1353         D3DPSREGISTER_ScreenToDepth = 33,
1354         D3DPSREGISTER_ShadowMap_Parameters = 34,
1355         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1356         D3DPSREGISTER_SpecularPower = 36,
1357         D3DPSREGISTER_UserVec1 = 37,
1358         D3DPSREGISTER_UserVec2 = 38,
1359         D3DPSREGISTER_UserVec3 = 39,
1360         D3DPSREGISTER_UserVec4 = 40,
1361         D3DPSREGISTER_ViewTintColor = 41,
1362         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1363         D3DPSREGISTER_BloomColorSubtract = 43,
1364         D3DPSREGISTER_ViewToLight = 44, // float4x4
1365         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1366         D3DPSREGISTER_NormalmapScrollBlend = 52,
1367         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1368         D3DPSREGISTER_OffsetMapping_Bias = 54,
1369         // next at 54
1370 }
1371 D3DPSREGISTER_t;
1372
1373 /// information about each possible shader permutation
1374 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1375 /// currently selected permutation
1376 r_hlsl_permutation_t *r_hlsl_permutation;
1377 /// storage for permutations linked in the hash table
1378 memexpandablearray_t r_hlsl_permutationarray;
1379
1380 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1381 {
1382         //unsigned int hashdepth = 0;
1383         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1384         r_hlsl_permutation_t *p;
1385         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1386         {
1387                 if (p->mode == mode && p->permutation == permutation)
1388                 {
1389                         //if (hashdepth > 10)
1390                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1391                         return p;
1392                 }
1393                 //hashdepth++;
1394         }
1395         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1396         p->mode = mode;
1397         p->permutation = permutation;
1398         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1399         r_hlsl_permutationhash[mode][hashindex] = p;
1400         //if (hashdepth > 10)
1401         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1402         return p;
1403 }
1404
1405 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1406 {
1407         char *shaderstring;
1408         if (!filename || !filename[0])
1409                 return NULL;
1410         if (!strcmp(filename, "hlsl/default.hlsl"))
1411         {
1412                 if (!hlslshaderstring)
1413                 {
1414                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1415                         if (hlslshaderstring)
1416                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1417                         else
1418                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1419                 }
1420                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1421                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1422                 return shaderstring;
1423         }
1424         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425         if (shaderstring)
1426         {
1427                 if (printfromdisknotice)
1428                         Con_DPrintf("from disk %s... ", filename);
1429                 return shaderstring;
1430         }
1431         return shaderstring;
1432 }
1433
1434 #include <d3dx9.h>
1435 //#include <d3dx9shader.h>
1436 //#include <d3dx9mesh.h>
1437
1438 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1439 {
1440         DWORD *vsbin = NULL;
1441         DWORD *psbin = NULL;
1442         fs_offset_t vsbinsize;
1443         fs_offset_t psbinsize;
1444 //      IDirect3DVertexShader9 *vs = NULL;
1445 //      IDirect3DPixelShader9 *ps = NULL;
1446         ID3DXBuffer *vslog = NULL;
1447         ID3DXBuffer *vsbuffer = NULL;
1448         ID3DXConstantTable *vsconstanttable = NULL;
1449         ID3DXBuffer *pslog = NULL;
1450         ID3DXBuffer *psbuffer = NULL;
1451         ID3DXConstantTable *psconstanttable = NULL;
1452         int vsresult = 0;
1453         int psresult = 0;
1454         char temp[MAX_INPUTLINE];
1455         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1456         char vabuf[1024];
1457         qboolean debugshader = gl_paranoid.integer != 0;
1458         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1459         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1460         if (!debugshader)
1461         {
1462                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1463                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1464         }
1465         if ((!vsbin && vertstring) || (!psbin && fragstring))
1466         {
1467                 const char* dllnames_d3dx9 [] =
1468                 {
1469                         "d3dx9_43.dll",
1470                         "d3dx9_42.dll",
1471                         "d3dx9_41.dll",
1472                         "d3dx9_40.dll",
1473                         "d3dx9_39.dll",
1474                         "d3dx9_38.dll",
1475                         "d3dx9_37.dll",
1476                         "d3dx9_36.dll",
1477                         "d3dx9_35.dll",
1478                         "d3dx9_34.dll",
1479                         "d3dx9_33.dll",
1480                         "d3dx9_32.dll",
1481                         "d3dx9_31.dll",
1482                         "d3dx9_30.dll",
1483                         "d3dx9_29.dll",
1484                         "d3dx9_28.dll",
1485                         "d3dx9_27.dll",
1486                         "d3dx9_26.dll",
1487                         "d3dx9_25.dll",
1488                         "d3dx9_24.dll",
1489                         NULL
1490                 };
1491                 dllhandle_t d3dx9_dll = NULL;
1492                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1493                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1494                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1495                 dllfunction_t d3dx9_dllfuncs[] =
1496                 {
1497                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1498                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1499                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1500                         {NULL, NULL}
1501                 };
1502                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1503                 {
1504                         DWORD shaderflags = 0;
1505                         if (debugshader)
1506                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1507                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1508                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1509                         if (vertstring && vertstring[0])
1510                         {
1511                                 if (debugshader)
1512                                 {
1513 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1514 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1515                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1516                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1517                                 }
1518                                 else
1519                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1520                                 if (vsbuffer)
1521                                 {
1522                                         vsbinsize = vsbuffer->GetBufferSize();
1523                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1524                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1525                                         vsbuffer->Release();
1526                                 }
1527                                 if (vslog)
1528                                 {
1529                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1530                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1531                                         vslog->Release();
1532                                 }
1533                         }
1534                         if (fragstring && fragstring[0])
1535                         {
1536                                 if (debugshader)
1537                                 {
1538 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1539 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1540                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1541                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1542                                 }
1543                                 else
1544                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1545                                 if (psbuffer)
1546                                 {
1547                                         psbinsize = psbuffer->GetBufferSize();
1548                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1549                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1550                                         psbuffer->Release();
1551                                 }
1552                                 if (pslog)
1553                                 {
1554                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1555                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1556                                         pslog->Release();
1557                                 }
1558                         }
1559                         Sys_UnloadLibrary(&d3dx9_dll);
1560                 }
1561                 else
1562                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1563         }
1564         if (vsbin && psbin)
1565         {
1566                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1567                 if (FAILED(vsresult))
1568                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1569                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1570                 if (FAILED(psresult))
1571                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1572         }
1573         // free the shader data
1574         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1575         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1576 }
1577
1578 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1579 {
1580         int i;
1581         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1582         int vertstring_length = 0;
1583         int geomstring_length = 0;
1584         int fragstring_length = 0;
1585         char *t;
1586         char *vertexstring, *geometrystring, *fragmentstring;
1587         char *vertstring, *geomstring, *fragstring;
1588         char permutationname[256];
1589         char cachename[256];
1590         int vertstrings_count = 0;
1591         int geomstrings_count = 0;
1592         int fragstrings_count = 0;
1593         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1594         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596
1597         if (p->compiled)
1598                 return;
1599         p->compiled = true;
1600         p->vertexshader = NULL;
1601         p->pixelshader = NULL;
1602
1603         permutationname[0] = 0;
1604         cachename[0] = 0;
1605         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1606         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1607         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1608
1609         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1610         strlcat(cachename, "hlsl/", sizeof(cachename));
1611
1612         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1613         vertstrings_count = 0;
1614         geomstrings_count = 0;
1615         fragstrings_count = 0;
1616         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1617         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1618         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1619
1620         // the first pretext is which type of shader to compile as
1621         // (later these will all be bound together as a program object)
1622         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1623         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1624         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1625
1626         // the second pretext is the mode (for example a light source)
1627         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1628         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1629         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1630         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1631         strlcat(cachename, modeinfo->name, sizeof(cachename));
1632
1633         // now add all the permutation pretexts
1634         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1635         {
1636                 if (permutation & (1<<i))
1637                 {
1638                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1639                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1642                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1643                 }
1644                 else
1645                 {
1646                         // keep line numbers correct
1647                         vertstrings_list[vertstrings_count++] = "\n";
1648                         geomstrings_list[geomstrings_count++] = "\n";
1649                         fragstrings_list[fragstrings_count++] = "\n";
1650                 }
1651         }
1652
1653         // add static parms
1654         R_CompileShader_AddStaticParms(mode, permutation);
1655         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1656         vertstrings_count += shaderstaticparms_count;
1657         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658         geomstrings_count += shaderstaticparms_count;
1659         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1660         fragstrings_count += shaderstaticparms_count;
1661
1662         // replace spaces in the cachename with _ characters
1663         for (i = 0;cachename[i];i++)
1664                 if (cachename[i] == ' ')
1665                         cachename[i] = '_';
1666
1667         // now append the shader text itself
1668         vertstrings_list[vertstrings_count++] = vertexstring;
1669         geomstrings_list[geomstrings_count++] = geometrystring;
1670         fragstrings_list[fragstrings_count++] = fragmentstring;
1671
1672         // if any sources were NULL, clear the respective list
1673         if (!vertexstring)
1674                 vertstrings_count = 0;
1675         if (!geometrystring)
1676                 geomstrings_count = 0;
1677         if (!fragmentstring)
1678                 fragstrings_count = 0;
1679
1680         vertstring_length = 0;
1681         for (i = 0;i < vertstrings_count;i++)
1682                 vertstring_length += strlen(vertstrings_list[i]);
1683         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1684         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1685                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1686
1687         geomstring_length = 0;
1688         for (i = 0;i < geomstrings_count;i++)
1689                 geomstring_length += strlen(geomstrings_list[i]);
1690         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1691         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1692                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1693
1694         fragstring_length = 0;
1695         for (i = 0;i < fragstrings_count;i++)
1696                 fragstring_length += strlen(fragstrings_list[i]);
1697         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1698         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1699                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1700
1701         // try to load the cached shader, or generate one
1702         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1703
1704         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1705                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1706         else
1707                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1708
1709         // free the strings
1710         if (vertstring)
1711                 Mem_Free(vertstring);
1712         if (geomstring)
1713                 Mem_Free(geomstring);
1714         if (fragstring)
1715                 Mem_Free(fragstring);
1716         if (vertexstring)
1717                 Mem_Free(vertexstring);
1718         if (geometrystring)
1719                 Mem_Free(geometrystring);
1720         if (fragmentstring)
1721                 Mem_Free(fragmentstring);
1722 }
1723
1724 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1725 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1726 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);}
1727 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);}
1728 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);}
1729 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);}
1730
1731 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 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);}
1734 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);}
1735 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);}
1736 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);}
1737
1738 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1739 {
1740         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1741         if (r_hlsl_permutation != perm)
1742         {
1743                 r_hlsl_permutation = perm;
1744                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1745                 {
1746                         if (!r_hlsl_permutation->compiled)
1747                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1748                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1749                         {
1750                                 // remove features until we find a valid permutation
1751                                 int i;
1752                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1753                                 {
1754                                         // reduce i more quickly whenever it would not remove any bits
1755                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1756                                         if (!(permutation & j))
1757                                                 continue;
1758                                         permutation -= j;
1759                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1760                                         if (!r_hlsl_permutation->compiled)
1761                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1762                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1763                                                 break;
1764                                 }
1765                                 if (i >= SHADERPERMUTATION_COUNT)
1766                                 {
1767                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1768                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1769                                         return; // no bit left to clear, entire mode is broken
1770                                 }
1771                         }
1772                 }
1773                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1774                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1775         }
1776         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1777         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1778         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1779 }
1780 #endif
1781
1782 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1783 {
1784         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1785         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1786         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1787         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1788 }
1789
1790 static void R_GLSL_Restart_f(void)
1791 {
1792         unsigned int i, limit;
1793         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1794                 Mem_Free(glslshaderstring);
1795         glslshaderstring = NULL;
1796         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1797                 Mem_Free(hlslshaderstring);
1798         hlslshaderstring = NULL;
1799         switch(vid.renderpath)
1800         {
1801         case RENDERPATH_D3D9:
1802 #ifdef SUPPORTD3D
1803                 {
1804                         r_hlsl_permutation_t *p;
1805                         r_hlsl_permutation = NULL;
1806                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1807                         for (i = 0;i < limit;i++)
1808                         {
1809                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1810                                 {
1811                                         if (p->vertexshader)
1812                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1813                                         if (p->pixelshader)
1814                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1815                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1816                                 }
1817                         }
1818                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1819                 }
1820 #endif
1821                 break;
1822         case RENDERPATH_D3D10:
1823                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1824                 break;
1825         case RENDERPATH_D3D11:
1826                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1827                 break;
1828         case RENDERPATH_GL20:
1829         case RENDERPATH_GLES2:
1830                 {
1831                         r_glsl_permutation_t *p;
1832                         r_glsl_permutation = NULL;
1833                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1834                         for (i = 0;i < limit;i++)
1835                         {
1836                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1837                                 {
1838                                         GL_Backend_FreeProgram(p->program);
1839                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1840                                 }
1841                         }
1842                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1843                 }
1844                 break;
1845         case RENDERPATH_GL11:
1846         case RENDERPATH_GL13:
1847         case RENDERPATH_GLES1:
1848                 break;
1849         case RENDERPATH_SOFT:
1850                 break;
1851         }
1852 }
1853
1854 static void R_GLSL_DumpShader_f(void)
1855 {
1856         int i;
1857         qfile_t *file;
1858
1859         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1860         if (file)
1861         {
1862                 FS_Print(file, "/* The engine may define the following macros:\n");
1863                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1864                 for (i = 0;i < SHADERMODE_COUNT;i++)
1865                         FS_Print(file, glslshadermodeinfo[i].pretext);
1866                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1867                         FS_Print(file, shaderpermutationinfo[i].pretext);
1868                 FS_Print(file, "*/\n");
1869                 FS_Print(file, builtinshaderstring);
1870                 FS_Close(file);
1871                 Con_Printf("glsl/default.glsl written\n");
1872         }
1873         else
1874                 Con_Printf("failed to write to glsl/default.glsl\n");
1875
1876         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1877         if (file)
1878         {
1879                 FS_Print(file, "/* The engine may define the following macros:\n");
1880                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1881                 for (i = 0;i < SHADERMODE_COUNT;i++)
1882                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1883                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884                         FS_Print(file, shaderpermutationinfo[i].pretext);
1885                 FS_Print(file, "*/\n");
1886                 FS_Print(file, builtinhlslshaderstring);
1887                 FS_Close(file);
1888                 Con_Printf("hlsl/default.hlsl written\n");
1889         }
1890         else
1891                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1892 }
1893
1894 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1895 {
1896         unsigned int permutation = 0;
1897         if (r_trippy.integer && !notrippy)
1898                 permutation |= SHADERPERMUTATION_TRIPPY;
1899         permutation |= SHADERPERMUTATION_VIEWTINT;
1900         if (first)
1901                 permutation |= SHADERPERMUTATION_DIFFUSE;
1902         if (second)
1903                 permutation |= SHADERPERMUTATION_SPECULAR;
1904         if (texturemode == GL_MODULATE)
1905                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1906         else if (texturemode == GL_ADD)
1907                 permutation |= SHADERPERMUTATION_GLOW;
1908         else if (texturemode == GL_DECAL)
1909                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1910         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1911                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1912         if (suppresstexalpha)
1913                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1914         if (!second)
1915                 texturemode = GL_MODULATE;
1916         if (vid.allowalphatocoverage)
1917                 GL_AlphaToCoverage(false);
1918         switch (vid.renderpath)
1919         {
1920         case RENDERPATH_D3D9:
1921 #ifdef SUPPORTD3D
1922                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1923                 R_Mesh_TexBind(GL20TU_FIRST , first );
1924                 R_Mesh_TexBind(GL20TU_SECOND, second);
1925                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1926                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1927 #endif
1928                 break;
1929         case RENDERPATH_D3D10:
1930                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931                 break;
1932         case RENDERPATH_D3D11:
1933                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1934                 break;
1935         case RENDERPATH_GL20:
1936         case RENDERPATH_GLES2:
1937                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1938                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1939                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1940                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1941                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1942                 break;
1943         case RENDERPATH_GL13:
1944         case RENDERPATH_GLES1:
1945                 R_Mesh_TexBind(0, first );
1946                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1947                 R_Mesh_TexBind(1, second);
1948                 if (second)
1949                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1950                 break;
1951         case RENDERPATH_GL11:
1952                 R_Mesh_TexBind(0, first );
1953                 break;
1954         case RENDERPATH_SOFT:
1955                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1956                 R_Mesh_TexBind(GL20TU_FIRST , first );
1957                 R_Mesh_TexBind(GL20TU_SECOND, second);
1958                 break;
1959         }
1960 }
1961
1962 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1963 {
1964         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1965 }
1966
1967 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1968 {
1969         unsigned int permutation = 0;
1970         if (r_trippy.integer && !notrippy)
1971                 permutation |= SHADERPERMUTATION_TRIPPY;
1972         if (vid.allowalphatocoverage)
1973                 GL_AlphaToCoverage(false);
1974         switch (vid.renderpath)
1975         {
1976         case RENDERPATH_D3D9:
1977 #ifdef SUPPORTD3D
1978                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1979 #endif
1980                 break;
1981         case RENDERPATH_D3D10:
1982                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1983                 break;
1984         case RENDERPATH_D3D11:
1985                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1986                 break;
1987         case RENDERPATH_GL20:
1988         case RENDERPATH_GLES2:
1989                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1990                 break;
1991         case RENDERPATH_GL13:
1992         case RENDERPATH_GLES1:
1993                 R_Mesh_TexBind(0, 0);
1994                 R_Mesh_TexBind(1, 0);
1995                 break;
1996         case RENDERPATH_GL11:
1997                 R_Mesh_TexBind(0, 0);
1998                 break;
1999         case RENDERPATH_SOFT:
2000                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2001                 break;
2002         }
2003 }
2004
2005 void R_SetupShader_ShowDepth(qboolean notrippy)
2006 {
2007         int permutation = 0;
2008         if (r_trippy.integer && !notrippy)
2009                 permutation |= SHADERPERMUTATION_TRIPPY;
2010         if (vid.allowalphatocoverage)
2011                 GL_AlphaToCoverage(false);
2012         switch (vid.renderpath)
2013         {
2014         case RENDERPATH_D3D9:
2015 #ifdef SUPPORTHLSL
2016                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2017 #endif
2018                 break;
2019         case RENDERPATH_D3D10:
2020                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2021                 break;
2022         case RENDERPATH_D3D11:
2023                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2024                 break;
2025         case RENDERPATH_GL20:
2026         case RENDERPATH_GLES2:
2027                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2028                 break;
2029         case RENDERPATH_GL13:
2030         case RENDERPATH_GLES1:
2031                 break;
2032         case RENDERPATH_GL11:
2033                 break;
2034         case RENDERPATH_SOFT:
2035                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2036                 break;
2037         }
2038 }
2039
2040 extern qboolean r_shadow_usingdeferredprepass;
2041 extern cvar_t r_shadow_deferred_8bitrange;
2042 extern rtexture_t *r_shadow_attenuationgradienttexture;
2043 extern rtexture_t *r_shadow_attenuation2dtexture;
2044 extern rtexture_t *r_shadow_attenuation3dtexture;
2045 extern qboolean r_shadow_usingshadowmap2d;
2046 extern qboolean r_shadow_usingshadowmaportho;
2047 extern float r_shadow_shadowmap_texturescale[2];
2048 extern float r_shadow_shadowmap_parameters[4];
2049 extern qboolean r_shadow_shadowmapvsdct;
2050 extern qboolean r_shadow_shadowmapsampler;
2051 extern int r_shadow_shadowmappcf;
2052 extern rtexture_t *r_shadow_shadowmap2dtexture;
2053 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2054 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2055 extern matrix4x4_t r_shadow_shadowmapmatrix;
2056 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2057 extern int r_shadow_prepass_width;
2058 extern int r_shadow_prepass_height;
2059 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2060 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2061 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2062 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2063 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2064
2065 #define BLENDFUNC_ALLOWS_COLORMOD      1
2066 #define BLENDFUNC_ALLOWS_FOG           2
2067 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2068 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2069 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2070 static int R_BlendFuncFlags(int src, int dst)
2071 {
2072         int r = 0;
2073
2074         // a blendfunc allows colormod if:
2075         // a) it can never keep the destination pixel invariant, or
2076         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2077         // this is to prevent unintended side effects from colormod
2078
2079         // a blendfunc allows fog if:
2080         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2081         // this is to prevent unintended side effects from fog
2082
2083         // these checks are the output of fogeval.pl
2084
2085         r |= BLENDFUNC_ALLOWS_COLORMOD;
2086         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2087         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2090         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2092         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2093         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2095         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2098         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2099         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2101         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2102         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2104         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2105         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107
2108         return r;
2109 }
2110
2111 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)
2112 {
2113         // select a permutation of the lighting shader appropriate to this
2114         // combination of texture, entity, light source, and fogging, only use the
2115         // minimum features necessary to avoid wasting rendering time in the
2116         // fragment shader on features that are not being used
2117         unsigned int permutation = 0;
2118         unsigned int mode = 0;
2119         int blendfuncflags;
2120         static float dummy_colormod[3] = {1, 1, 1};
2121         float *colormod = rsurface.colormod;
2122         float m16f[16];
2123         matrix4x4_t tempmatrix;
2124         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2125         if (r_trippy.integer && !notrippy)
2126                 permutation |= SHADERPERMUTATION_TRIPPY;
2127         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2128                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2129         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2130                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2131         if (rsurfacepass == RSURFPASS_BACKGROUND)
2132         {
2133                 // distorted background
2134                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2135                 {
2136                         mode = SHADERMODE_WATER;
2137                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2138                         {
2139                                 // this is the right thing to do for wateralpha
2140                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2141                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2142                         }
2143                         else
2144                         {
2145                                 // this is the right thing to do for entity alpha
2146                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2148                         }
2149                 }
2150                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2151                 {
2152                         mode = SHADERMODE_REFRACTION;
2153                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2155                 }
2156                 else
2157                 {
2158                         mode = SHADERMODE_GENERIC;
2159                         permutation |= SHADERPERMUTATION_DIFFUSE;
2160                         GL_BlendFunc(GL_ONE, GL_ZERO);
2161                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2162                 }
2163                 if (vid.allowalphatocoverage)
2164                         GL_AlphaToCoverage(false);
2165         }
2166         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2167         {
2168                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2169                 {
2170                         switch(rsurface.texture->offsetmapping)
2171                         {
2172                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2173                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2174                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2175                         case OFFSETMAPPING_OFF: break;
2176                         }
2177                 }
2178                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2179                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2180                 // normalmap (deferred prepass), may use alpha test on diffuse
2181                 mode = SHADERMODE_DEFERREDGEOMETRY;
2182                 GL_BlendFunc(GL_ONE, GL_ZERO);
2183                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2184                 if (vid.allowalphatocoverage)
2185                         GL_AlphaToCoverage(false);
2186         }
2187         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2188         {
2189                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2190                 {
2191                         switch(rsurface.texture->offsetmapping)
2192                         {
2193                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2194                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196                         case OFFSETMAPPING_OFF: break;
2197                         }
2198                 }
2199                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2200                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2201                 // light source
2202                 mode = SHADERMODE_LIGHTSOURCE;
2203                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2204                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2205                 if (diffusescale > 0)
2206                         permutation |= SHADERPERMUTATION_DIFFUSE;
2207                 if (specularscale > 0)
2208                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2209                 if (r_refdef.fogenabled)
2210                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2211                 if (rsurface.texture->colormapping)
2212                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2213                 if (r_shadow_usingshadowmap2d)
2214                 {
2215                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2216                         if(r_shadow_shadowmapvsdct)
2217                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2218
2219                         if (r_shadow_shadowmapsampler)
2220                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2221                         if (r_shadow_shadowmappcf > 1)
2222                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2223                         else if (r_shadow_shadowmappcf)
2224                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2225                 }
2226                 if (rsurface.texture->reflectmasktexture)
2227                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2228                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2229                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2230                 if (vid.allowalphatocoverage)
2231                         GL_AlphaToCoverage(false);
2232         }
2233         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2234         {
2235                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2236                 {
2237                         switch(rsurface.texture->offsetmapping)
2238                         {
2239                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2240                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_OFF: break;
2243                         }
2244                 }
2245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2246                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2247                 // unshaded geometry (fullbright or ambient model lighting)
2248                 mode = SHADERMODE_FLATCOLOR;
2249                 ambientscale = diffusescale = specularscale = 0;
2250                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2251                         permutation |= SHADERPERMUTATION_GLOW;
2252                 if (r_refdef.fogenabled)
2253                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2254                 if (rsurface.texture->colormapping)
2255                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2256                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2257                 {
2258                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2259                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2260
2261                         if (r_shadow_shadowmapsampler)
2262                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2263                         if (r_shadow_shadowmappcf > 1)
2264                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2265                         else if (r_shadow_shadowmappcf)
2266                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2267                 }
2268                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2269                         permutation |= SHADERPERMUTATION_REFLECTION;
2270                 if (rsurface.texture->reflectmasktexture)
2271                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2272                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2273                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2274                 // when using alphatocoverage, we don't need alphakill
2275                 if (vid.allowalphatocoverage)
2276                 {
2277                         if (r_transparent_alphatocoverage.integer)
2278                         {
2279                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2280                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2281                         }
2282                         else
2283                                 GL_AlphaToCoverage(false);
2284                 }
2285         }
2286         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2287         {
2288                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2289                 {
2290                         switch(rsurface.texture->offsetmapping)
2291                         {
2292                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2293                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2294                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295                         case OFFSETMAPPING_OFF: break;
2296                         }
2297                 }
2298                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2299                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2300                 // directional model lighting
2301                 mode = SHADERMODE_LIGHTDIRECTION;
2302                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2303                         permutation |= SHADERPERMUTATION_GLOW;
2304                 permutation |= SHADERPERMUTATION_DIFFUSE;
2305                 if (specularscale > 0)
2306                         permutation |= SHADERPERMUTATION_SPECULAR;
2307                 if (r_refdef.fogenabled)
2308                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2309                 if (rsurface.texture->colormapping)
2310                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2311                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2312                 {
2313                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2314                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2315
2316                         if (r_shadow_shadowmapsampler)
2317                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2318                         if (r_shadow_shadowmappcf > 1)
2319                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2320                         else if (r_shadow_shadowmappcf)
2321                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2322                 }
2323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2324                         permutation |= SHADERPERMUTATION_REFLECTION;
2325                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2326                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2327                 if (rsurface.texture->reflectmasktexture)
2328                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2329                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2330                 {
2331                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2332                         if (r_shadow_bouncegriddirectional)
2333                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2334                 }
2335                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2337                 // when using alphatocoverage, we don't need alphakill
2338                 if (vid.allowalphatocoverage)
2339                 {
2340                         if (r_transparent_alphatocoverage.integer)
2341                         {
2342                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2343                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2344                         }
2345                         else
2346                                 GL_AlphaToCoverage(false);
2347                 }
2348         }
2349         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2350         {
2351                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2352                 {
2353                         switch(rsurface.texture->offsetmapping)
2354                         {
2355                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2356                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2357                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2358                         case OFFSETMAPPING_OFF: break;
2359                         }
2360                 }
2361                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2362                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2363                 // ambient model lighting
2364                 mode = SHADERMODE_LIGHTDIRECTION;
2365                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2366                         permutation |= SHADERPERMUTATION_GLOW;
2367                 if (r_refdef.fogenabled)
2368                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2369                 if (rsurface.texture->colormapping)
2370                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2371                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2372                 {
2373                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2374                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2375
2376                         if (r_shadow_shadowmapsampler)
2377                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2378                         if (r_shadow_shadowmappcf > 1)
2379                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2380                         else if (r_shadow_shadowmappcf)
2381                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2382                 }
2383                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2384                         permutation |= SHADERPERMUTATION_REFLECTION;
2385                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2386                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2387                 if (rsurface.texture->reflectmasktexture)
2388                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2389                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2390                 {
2391                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2392                         if (r_shadow_bouncegriddirectional)
2393                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2394                 }
2395                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2396                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2397                 // when using alphatocoverage, we don't need alphakill
2398                 if (vid.allowalphatocoverage)
2399                 {
2400                         if (r_transparent_alphatocoverage.integer)
2401                         {
2402                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2403                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2404                         }
2405                         else
2406                                 GL_AlphaToCoverage(false);
2407                 }
2408         }
2409         else
2410         {
2411                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2412                 {
2413                         switch(rsurface.texture->offsetmapping)
2414                         {
2415                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2416                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2417                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2418                         case OFFSETMAPPING_OFF: break;
2419                         }
2420                 }
2421                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2422                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2423                 // lightmapped wall
2424                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2425                         permutation |= SHADERPERMUTATION_GLOW;
2426                 if (r_refdef.fogenabled)
2427                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2428                 if (rsurface.texture->colormapping)
2429                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2430                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2431                 {
2432                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2433                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2434
2435                         if (r_shadow_shadowmapsampler)
2436                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2437                         if (r_shadow_shadowmappcf > 1)
2438                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2439                         else if (r_shadow_shadowmappcf)
2440                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2441                 }
2442                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2443                         permutation |= SHADERPERMUTATION_REFLECTION;
2444                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2445                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2446                 if (rsurface.texture->reflectmasktexture)
2447                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2448                 if (FAKELIGHT_ENABLED)
2449                 {
2450                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2451                         mode = SHADERMODE_FAKELIGHT;
2452                         permutation |= SHADERPERMUTATION_DIFFUSE;
2453                         if (specularscale > 0)
2454                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2455                 }
2456                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2457                 {
2458                         // deluxemapping (light direction texture)
2459                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2460                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2461                         else
2462                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2463                         permutation |= SHADERPERMUTATION_DIFFUSE;
2464                         if (specularscale > 0)
2465                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2466                 }
2467                 else if (r_glsl_deluxemapping.integer >= 2)
2468                 {
2469                         // fake deluxemapping (uniform light direction in tangentspace)
2470                         if (rsurface.uselightmaptexture)
2471                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2472                         else
2473                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2474                         permutation |= SHADERPERMUTATION_DIFFUSE;
2475                         if (specularscale > 0)
2476                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2477                 }
2478                 else if (rsurface.uselightmaptexture)
2479                 {
2480                         // ordinary lightmapping (q1bsp, q3bsp)
2481                         mode = SHADERMODE_LIGHTMAP;
2482                 }
2483                 else
2484                 {
2485                         // ordinary vertex coloring (q3bsp)
2486                         mode = SHADERMODE_VERTEXCOLOR;
2487                 }
2488                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2489                 {
2490                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2491                         if (r_shadow_bouncegriddirectional)
2492                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2493                 }
2494                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2495                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2496                 // when using alphatocoverage, we don't need alphakill
2497                 if (vid.allowalphatocoverage)
2498                 {
2499                         if (r_transparent_alphatocoverage.integer)
2500                         {
2501                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2502                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2503                         }
2504                         else
2505                                 GL_AlphaToCoverage(false);
2506                 }
2507         }
2508         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2509                 colormod = dummy_colormod;
2510         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2511                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2512         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2513                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2514         switch(vid.renderpath)
2515         {
2516         case RENDERPATH_D3D9:
2517 #ifdef SUPPORTD3D
2518                 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);
2519                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2520                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2521                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2522                 if (mode == SHADERMODE_LIGHTSOURCE)
2523                 {
2524                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2525                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2526                 }
2527                 else
2528                 {
2529                         if (mode == SHADERMODE_LIGHTDIRECTION)
2530                         {
2531                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2532                         }
2533                 }
2534                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2535                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2536                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2537                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2538                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2539
2540                 if (mode == SHADERMODE_LIGHTSOURCE)
2541                 {
2542                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2545                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2546                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2547
2548                         // additive passes are only darkened by fog, not tinted
2549                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2550                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2551                 }
2552                 else
2553                 {
2554                         if (mode == SHADERMODE_FLATCOLOR)
2555                         {
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2557                         }
2558                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2559                         {
2560                                 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]);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2562                                 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);
2563                                 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);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2567                         }
2568                         else
2569                         {
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2572                                 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);
2573                                 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);
2574                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2575                         }
2576                         // additive passes are only darkened by fog, not tinted
2577                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2579                         else
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2581                         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);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2584                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2585                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2587                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2588                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2589                         if (mode == SHADERMODE_WATER)
2590                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2591                 }
2592                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2593                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2594                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2595                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2596                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2597                 if (rsurface.texture->pantstexture)
2598                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2599                 else
2600                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2601                 if (rsurface.texture->shirttexture)
2602                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2603                 else
2604                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2605                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2607                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2608                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2609                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2610                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2611                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2612                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2613                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2614                         );
2615                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2616                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2617                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2618                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2619
2620                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2621                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2622                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2623                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2624                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2625                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2626                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2627                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2628                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2629                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2630                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2631                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2632                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2633                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2634                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2635                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2636                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2637                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2638                 {
2639                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2640                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2641                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2642                 }
2643                 else
2644                 {
2645                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2646                 }
2647 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2648 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2649                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2650                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2651                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2652                 {
2653                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2654                         if (rsurface.rtlight)
2655                         {
2656                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2657                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2658                         }
2659                 }
2660 #endif
2661                 break;
2662         case RENDERPATH_D3D10:
2663                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2664                 break;
2665         case RENDERPATH_D3D11:
2666                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2667                 break;
2668         case RENDERPATH_GL20:
2669         case RENDERPATH_GLES2:
2670                 if (!vid.useinterleavedarrays)
2671                 {
2672                         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);
2673                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2674                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2676                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2677                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2678                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2679                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2680                 }
2681                 else
2682                 {
2683                         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);
2684                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2685                 }
2686                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2687                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2688                 if (mode == SHADERMODE_LIGHTSOURCE)
2689                 {
2690                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2691                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2692                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2693                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2694                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2695                         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);
2696         
2697                         // additive passes are only darkened by fog, not tinted
2698                         if (r_glsl_permutation->loc_FogColor >= 0)
2699                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2700                         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);
2701                 }
2702                 else
2703                 {
2704                         if (mode == SHADERMODE_FLATCOLOR)
2705                         {
2706                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2707                         }
2708                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2709                         {
2710                                 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]);
2711                                 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]);
2712                                 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);
2713                                 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);
2714                                 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);
2715                                 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]);
2716                                 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]);
2717                         }
2718                         else
2719                         {
2720                                 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]);
2721                                 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]);
2722                                 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);
2723                                 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);
2724                                 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);
2725                         }
2726                         // additive passes are only darkened by fog, not tinted
2727                         if (r_glsl_permutation->loc_FogColor >= 0)
2728                         {
2729                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2730                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2731                                 else
2732                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2733                         }
2734                         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);
2735                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2736                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2737                         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]);
2738                         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]);
2739                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2740                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2741                         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);
2742                         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]);
2743                 }
2744                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2745                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2746                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2747                 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]);
2748                 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]);
2749
2750                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2751                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2752                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2753                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2754                 {
2755                         if (rsurface.texture->pantstexture)
2756                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2757                         else
2758                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2759                 }
2760                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2761                 {
2762                         if (rsurface.texture->shirttexture)
2763                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2764                         else
2765                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2766                 }
2767                 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]);
2768                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2769                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2770                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2771                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2772                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2773                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2774                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2775                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2776                         );
2777                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2778                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2779                 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]);
2780                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2781                 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);}
2782                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2783
2784                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2785                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2786                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2787                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2788                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2789                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2790                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2791                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2792                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2793                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2794                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2795                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2796                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2797                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2798                 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);
2799                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2800                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2801                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2802                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2803                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2804                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2805                 {
2806                         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);
2807                         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);
2808                         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);
2809                 }
2810                 else
2811                 {
2812                         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);
2813                 }
2814                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2815                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2816                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2817                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2818                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2819                 {
2820                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2821                         if (rsurface.rtlight)
2822                         {
2823                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2824                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2825                         }
2826                 }
2827                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2828                 CHECKGLERROR
2829                 break;
2830         case RENDERPATH_GL11:
2831         case RENDERPATH_GL13:
2832         case RENDERPATH_GLES1:
2833                 break;
2834         case RENDERPATH_SOFT:
2835                 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);
2836                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2837                 R_SetupShader_SetPermutationSoft(mode, permutation);
2838                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2839                 if (mode == SHADERMODE_LIGHTSOURCE)
2840                 {
2841                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2847         
2848                         // additive passes are only darkened by fog, not tinted
2849                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2850                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2851                 }
2852                 else
2853                 {
2854                         if (mode == SHADERMODE_FLATCOLOR)
2855                         {
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2857                         }
2858                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2859                         {
2860                                 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]);
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2862                                 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);
2863                                 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);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2865                                 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]);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2867                         }
2868                         else
2869                         {
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2872                                 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);
2873                                 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);
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2875                         }
2876                         // additive passes are only darkened by fog, not tinted
2877                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2879                         else
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2881                         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);
2882                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2883                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2884                         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]);
2885                         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]);
2886                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2887                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2888                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2889                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2890                 }
2891                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2892                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2893                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2894                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2895                 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]);
2896
2897                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2898                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2899                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2900                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2901                 {
2902                         if (rsurface.texture->pantstexture)
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2904                         else
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2906                 }
2907                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2908                 {
2909                         if (rsurface.texture->shirttexture)
2910                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2911                         else
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2913                 }
2914                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2917                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2918                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2919                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2920                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2921                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2922                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2923                         );
2924                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2925                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2926                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2927                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2928
2929                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2930                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2931                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2932                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2936                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2937                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2938                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2939                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2940                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2941                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2942                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2943                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2944                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2945                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2946                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2947                 {
2948                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2949                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2950                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2951                 }
2952                 else
2953                 {
2954                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2955                 }
2956 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2957 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2958                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2959                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2960                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2961                 {
2962                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2963                         if (rsurface.rtlight)
2964                         {
2965                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2966                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2967                         }
2968                 }
2969                 break;
2970         }
2971 }
2972
2973 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2974 {
2975         // select a permutation of the lighting shader appropriate to this
2976         // combination of texture, entity, light source, and fogging, only use the
2977         // minimum features necessary to avoid wasting rendering time in the
2978         // fragment shader on features that are not being used
2979         unsigned int permutation = 0;
2980         unsigned int mode = 0;
2981         const float *lightcolorbase = rtlight->currentcolor;
2982         float ambientscale = rtlight->ambientscale;
2983         float diffusescale = rtlight->diffusescale;
2984         float specularscale = rtlight->specularscale;
2985         // this is the location of the light in view space
2986         vec3_t viewlightorigin;
2987         // this transforms from view space (camera) to light space (cubemap)
2988         matrix4x4_t viewtolight;
2989         matrix4x4_t lighttoview;
2990         float viewtolight16f[16];
2991         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2992         // light source
2993         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2994         if (rtlight->currentcubemap != r_texture_whitecube)
2995                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2996         if (diffusescale > 0)
2997                 permutation |= SHADERPERMUTATION_DIFFUSE;
2998         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2999                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3000         if (r_shadow_usingshadowmap2d)
3001         {
3002                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3003                 if (r_shadow_shadowmapvsdct)
3004                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3005
3006                 if (r_shadow_shadowmapsampler)
3007                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3008                 if (r_shadow_shadowmappcf > 1)
3009                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3010                 else if (r_shadow_shadowmappcf)
3011                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3012         }
3013         if (vid.allowalphatocoverage)
3014                 GL_AlphaToCoverage(false);
3015         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3016         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3017         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3018         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3019         switch(vid.renderpath)
3020         {
3021         case RENDERPATH_D3D9:
3022 #ifdef SUPPORTD3D
3023                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3024                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3025                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3027                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3028                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3029                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3030                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3031                 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);
3032                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3033                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3034
3035                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3036                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3037                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3038                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3039                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3040                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3041 #endif
3042                 break;
3043         case RENDERPATH_D3D10:
3044                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3045                 break;
3046         case RENDERPATH_D3D11:
3047                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3048                 break;
3049         case RENDERPATH_GL20:
3050         case RENDERPATH_GLES2:
3051                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3052                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3053                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3054                 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);
3055                 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);
3056                 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);
3057                 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]);
3058                 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]);
3059                 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);
3060                 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]);
3061                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3062
3063                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3064                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3065                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3066                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3067                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3068                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3069                 break;
3070         case RENDERPATH_GL11:
3071         case RENDERPATH_GL13:
3072         case RENDERPATH_GLES1:
3073                 break;
3074         case RENDERPATH_SOFT:
3075                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3076                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3077                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3078                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3079                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3080                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3081                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3082                 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]);
3083                 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);
3084                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3085                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3086
3087                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3088                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3089                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3090                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3091                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3092                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3093                 break;
3094         }
3095 }
3096
3097 #define SKINFRAME_HASH 1024
3098
3099 typedef struct
3100 {
3101         int loadsequence; // incremented each level change
3102         memexpandablearray_t array;
3103         skinframe_t *hash[SKINFRAME_HASH];
3104 }
3105 r_skinframe_t;
3106 r_skinframe_t r_skinframe;
3107
3108 void R_SkinFrame_PrepareForPurge(void)
3109 {
3110         r_skinframe.loadsequence++;
3111         // wrap it without hitting zero
3112         if (r_skinframe.loadsequence >= 200)
3113                 r_skinframe.loadsequence = 1;
3114 }
3115
3116 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3117 {
3118         if (!skinframe)
3119                 return;
3120         // mark the skinframe as used for the purging code
3121         skinframe->loadsequence = r_skinframe.loadsequence;
3122 }
3123
3124 void R_SkinFrame_Purge(void)
3125 {
3126         int i;
3127         skinframe_t *s;
3128         for (i = 0;i < SKINFRAME_HASH;i++)
3129         {
3130                 for (s = r_skinframe.hash[i];s;s = s->next)
3131                 {
3132                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3133                         {
3134                                 if (s->merged == s->base)
3135                                         s->merged = NULL;
3136                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3137                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3138                                 R_PurgeTexture(s->merged);s->merged = NULL;
3139                                 R_PurgeTexture(s->base  );s->base   = NULL;
3140                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3141                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3142                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3143                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3144                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3145                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3146                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3147                                 s->loadsequence = 0;
3148                         }
3149                 }
3150         }
3151 }
3152
3153 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3154         skinframe_t *item;
3155         char basename[MAX_QPATH];
3156
3157         Image_StripImageExtension(name, basename, sizeof(basename));
3158
3159         if( last == NULL ) {
3160                 int hashindex;
3161                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3162                 item = r_skinframe.hash[hashindex];
3163         } else {
3164                 item = last->next;
3165         }
3166
3167         // linearly search through the hash bucket
3168         for( ; item ; item = item->next ) {
3169                 if( !strcmp( item->basename, basename ) ) {
3170                         return item;
3171                 }
3172         }
3173         return NULL;
3174 }
3175
3176 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3177 {
3178         skinframe_t *item;
3179         int hashindex;
3180         char basename[MAX_QPATH];
3181
3182         Image_StripImageExtension(name, basename, sizeof(basename));
3183
3184         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3185         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3186                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3187                         break;
3188
3189         if (!item) {
3190                 rtexture_t *dyntexture;
3191                 // check whether its a dynamic texture
3192                 dyntexture = CL_GetDynTexture( basename );
3193                 if (!add && !dyntexture)
3194                         return NULL;
3195                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3196                 memset(item, 0, sizeof(*item));
3197                 strlcpy(item->basename, basename, sizeof(item->basename));
3198                 item->base = dyntexture; // either NULL or dyntexture handle
3199                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3200                 item->comparewidth = comparewidth;
3201                 item->compareheight = compareheight;
3202                 item->comparecrc = comparecrc;
3203                 item->next = r_skinframe.hash[hashindex];
3204                 r_skinframe.hash[hashindex] = item;
3205         }
3206         else if (textureflags & TEXF_FORCE_RELOAD)
3207         {
3208                 rtexture_t *dyntexture;
3209                 // check whether its a dynamic texture
3210                 dyntexture = CL_GetDynTexture( basename );
3211                 if (!add && !dyntexture)
3212                         return NULL;
3213                 if (item->merged == item->base)
3214                         item->merged = NULL;
3215                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3216                 R_PurgeTexture(item->stain );item->stain  = NULL;
3217                 R_PurgeTexture(item->merged);item->merged = NULL;
3218                 R_PurgeTexture(item->base  );item->base   = NULL;
3219                 R_PurgeTexture(item->pants );item->pants  = NULL;
3220                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3221                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3222                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3223                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3224                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3225         R_PurgeTexture(item->reflect);item->reflect = NULL;
3226                 item->loadsequence = 0;
3227         }
3228         else if( item->base == NULL )
3229         {
3230                 rtexture_t *dyntexture;
3231                 // check whether its a dynamic texture
3232                 // 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]
3233                 dyntexture = CL_GetDynTexture( basename );
3234                 item->base = dyntexture; // either NULL or dyntexture handle
3235         }
3236
3237         R_SkinFrame_MarkUsed(item);
3238         return item;
3239 }
3240
3241 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3242         { \
3243                 unsigned long long avgcolor[5], wsum; \
3244                 int pix, comp, w; \
3245                 avgcolor[0] = 0; \
3246                 avgcolor[1] = 0; \
3247                 avgcolor[2] = 0; \
3248                 avgcolor[3] = 0; \
3249                 avgcolor[4] = 0; \
3250                 wsum = 0; \
3251                 for(pix = 0; pix < cnt; ++pix) \
3252                 { \
3253                         w = 0; \
3254                         for(comp = 0; comp < 3; ++comp) \
3255                                 w += getpixel; \
3256                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3257                         { \
3258                                 ++wsum; \
3259                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3260                                 w = getpixel; \
3261                                 for(comp = 0; comp < 3; ++comp) \
3262                                         avgcolor[comp] += getpixel * w; \
3263                                 avgcolor[3] += w; \
3264                         } \
3265                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3266                         avgcolor[4] += getpixel; \
3267                 } \
3268                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3269                         avgcolor[3] = 1; \
3270                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3271                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3272                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3273                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3274         }
3275
3276 extern cvar_t gl_picmip;
3277 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3278 {
3279         int j;
3280         unsigned char *pixels;
3281         unsigned char *bumppixels;
3282         unsigned char *basepixels = NULL;
3283         int basepixels_width = 0;
3284         int basepixels_height = 0;
3285         skinframe_t *skinframe;
3286         rtexture_t *ddsbase = NULL;
3287         qboolean ddshasalpha = false;
3288         float ddsavgcolor[4];
3289         char basename[MAX_QPATH];
3290         int miplevel = R_PicmipForFlags(textureflags);
3291         int savemiplevel = miplevel;
3292         int mymiplevel;
3293         char vabuf[1024];
3294
3295         if (cls.state == ca_dedicated)
3296                 return NULL;
3297
3298         // return an existing skinframe if already loaded
3299         // if loading of the first image fails, don't make a new skinframe as it
3300         // would cause all future lookups of this to be missing
3301         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3302         if (skinframe && skinframe->base)
3303                 return skinframe;
3304
3305         Image_StripImageExtension(name, basename, sizeof(basename));
3306
3307         // check for DDS texture file first
3308         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3309         {
3310                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3311                 if (basepixels == NULL)
3312                         return NULL;
3313         }
3314
3315         // FIXME handle miplevel
3316
3317         if (developer_loading.integer)
3318                 Con_Printf("loading skin \"%s\"\n", name);
3319
3320         // we've got some pixels to store, so really allocate this new texture now
3321         if (!skinframe)
3322                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3323         textureflags &= ~TEXF_FORCE_RELOAD;
3324         skinframe->stain = NULL;
3325         skinframe->merged = NULL;
3326         skinframe->base = NULL;
3327         skinframe->pants = NULL;
3328         skinframe->shirt = NULL;
3329         skinframe->nmap = NULL;
3330         skinframe->gloss = NULL;
3331         skinframe->glow = NULL;
3332         skinframe->fog = NULL;
3333         skinframe->reflect = NULL;
3334         skinframe->hasalpha = false;
3335
3336         if (ddsbase)
3337         {
3338                 skinframe->base = ddsbase;
3339                 skinframe->hasalpha = ddshasalpha;
3340                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3341                 if (r_loadfog && skinframe->hasalpha)
3342                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3343                 //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]);
3344         }
3345         else
3346         {
3347                 basepixels_width = image_width;
3348                 basepixels_height = image_height;
3349                 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);
3350                 if (textureflags & TEXF_ALPHA)
3351                 {
3352                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3353                         {
3354                                 if (basepixels[j] < 255)
3355                                 {
3356                                         skinframe->hasalpha = true;
3357                                         break;
3358                                 }
3359                         }
3360                         if (r_loadfog && skinframe->hasalpha)
3361                         {
3362                                 // has transparent pixels
3363                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3364                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3365                                 {
3366                                         pixels[j+0] = 255;
3367                                         pixels[j+1] = 255;
3368                                         pixels[j+2] = 255;
3369                                         pixels[j+3] = basepixels[j+3];
3370                                 }
3371                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3372                                 Mem_Free(pixels);
3373                         }
3374                 }
3375                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3376 #ifndef USE_GLES2
3377                 //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]);
3378                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3379                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3380                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3381                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3382 #endif
3383         }
3384
3385         if (r_loaddds)
3386         {
3387                 mymiplevel = savemiplevel;
3388                 if (r_loadnormalmap)
3389                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3390                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3391                 if (r_loadgloss)
3392                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3393                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3394                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3395                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3396         }
3397
3398         // _norm is the name used by tenebrae and has been adopted as standard
3399         if (r_loadnormalmap && skinframe->nmap == NULL)
3400         {
3401                 mymiplevel = savemiplevel;
3402                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3403                 {
3404                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3405                         Mem_Free(pixels);
3406                         pixels = NULL;
3407                 }
3408                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3409                 {
3410                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3411                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3412                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3413                         Mem_Free(pixels);
3414                         Mem_Free(bumppixels);
3415                 }
3416                 else if (r_shadow_bumpscale_basetexture.value > 0)
3417                 {
3418                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3419                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3420                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3421                         Mem_Free(pixels);
3422                 }
3423 #ifndef USE_GLES2
3424                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3425                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3426 #endif
3427         }
3428
3429         // _luma is supported only for tenebrae compatibility
3430         // _glow is the preferred name
3431         mymiplevel = savemiplevel;
3432         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3433         {
3434                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3435 #ifndef USE_GLES2
3436                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3437                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3438 #endif
3439                 Mem_Free(pixels);pixels = NULL;
3440         }
3441
3442         mymiplevel = savemiplevel;
3443         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3444         {
3445                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3446 #ifndef USE_GLES2
3447                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3448                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3449 #endif
3450                 Mem_Free(pixels);
3451                 pixels = NULL;
3452         }
3453
3454         mymiplevel = savemiplevel;
3455         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3456         {
3457                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3458 #ifndef USE_GLES2
3459                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3460                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3461 #endif
3462                 Mem_Free(pixels);
3463                 pixels = NULL;
3464         }
3465
3466         mymiplevel = savemiplevel;
3467         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3468         {
3469                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3470 #ifndef USE_GLES2
3471                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3472                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3473 #endif
3474                 Mem_Free(pixels);
3475                 pixels = NULL;
3476         }
3477
3478         mymiplevel = savemiplevel;
3479         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3480         {
3481                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3482 #ifndef USE_GLES2
3483                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3484                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3485 #endif
3486                 Mem_Free(pixels);
3487                 pixels = NULL;
3488         }
3489
3490         if (basepixels)
3491                 Mem_Free(basepixels);
3492
3493         return skinframe;
3494 }
3495
3496 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3497 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3498 {
3499         int i;
3500         unsigned char *temp1, *temp2;
3501         skinframe_t *skinframe;
3502         char vabuf[1024];
3503
3504         if (cls.state == ca_dedicated)
3505                 return NULL;
3506
3507         // if already loaded just return it, otherwise make a new skinframe
3508         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3509         if (skinframe && skinframe->base)
3510                 return skinframe;
3511         textureflags &= ~TEXF_FORCE_RELOAD;
3512
3513         skinframe->stain = NULL;
3514         skinframe->merged = NULL;
3515         skinframe->base = NULL;
3516         skinframe->pants = NULL;
3517         skinframe->shirt = NULL;
3518         skinframe->nmap = NULL;
3519         skinframe->gloss = NULL;
3520         skinframe->glow = NULL;
3521         skinframe->fog = NULL;
3522         skinframe->reflect = NULL;
3523         skinframe->hasalpha = false;
3524
3525         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3526         if (!skindata)
3527                 return NULL;
3528
3529         if (developer_loading.integer)
3530                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3531
3532         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3533         {
3534                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3535                 temp2 = temp1 + width * height * 4;
3536                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3537                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3538                 Mem_Free(temp1);
3539         }
3540         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3541         if (textureflags & TEXF_ALPHA)
3542         {
3543                 for (i = 3;i < width * height * 4;i += 4)
3544                 {
3545                         if (skindata[i] < 255)
3546                         {
3547                                 skinframe->hasalpha = true;
3548                                 break;
3549                         }
3550                 }
3551                 if (r_loadfog && skinframe->hasalpha)
3552                 {
3553                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3554                         memcpy(fogpixels, skindata, width * height * 4);
3555                         for (i = 0;i < width * height * 4;i += 4)
3556                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3557                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3558                         Mem_Free(fogpixels);
3559                 }
3560         }
3561
3562         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3563         //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]);
3564
3565         return skinframe;
3566 }
3567
3568 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3569 {
3570         int i;
3571         int featuresmask;
3572         skinframe_t *skinframe;
3573
3574         if (cls.state == ca_dedicated)
3575                 return NULL;
3576
3577         // if already loaded just return it, otherwise make a new skinframe
3578         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3579         if (skinframe && skinframe->base)
3580                 return skinframe;
3581         textureflags &= ~TEXF_FORCE_RELOAD;
3582
3583         skinframe->stain = NULL;
3584         skinframe->merged = NULL;
3585         skinframe->base = NULL;
3586         skinframe->pants = NULL;
3587         skinframe->shirt = NULL;
3588         skinframe->nmap = NULL;
3589         skinframe->gloss = NULL;
3590         skinframe->glow = NULL;
3591         skinframe->fog = NULL;
3592         skinframe->reflect = NULL;
3593         skinframe->hasalpha = false;
3594
3595         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3596         if (!skindata)
3597                 return NULL;
3598
3599         if (developer_loading.integer)
3600                 Con_Printf("loading quake skin \"%s\"\n", name);
3601
3602         // 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)
3603         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3604         memcpy(skinframe->qpixels, skindata, width*height);
3605         skinframe->qwidth = width;
3606         skinframe->qheight = height;
3607
3608         featuresmask = 0;
3609         for (i = 0;i < width * height;i++)
3610                 featuresmask |= palette_featureflags[skindata[i]];
3611
3612         skinframe->hasalpha = false;
3613         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3614         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3615         skinframe->qgeneratemerged = true;
3616         skinframe->qgeneratebase = skinframe->qhascolormapping;
3617         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3618
3619         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3620         //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]);
3621
3622         return skinframe;
3623 }
3624
3625 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3626 {
3627         int width;
3628         int height;
3629         unsigned char *skindata;
3630         char vabuf[1024];
3631
3632         if (!skinframe->qpixels)
3633                 return;
3634
3635         if (!skinframe->qhascolormapping)
3636                 colormapped = false;
3637
3638         if (colormapped)
3639         {
3640                 if (!skinframe->qgeneratebase)
3641                         return;
3642         }
3643         else
3644         {
3645                 if (!skinframe->qgeneratemerged)
3646                         return;
3647         }
3648
3649         width = skinframe->qwidth;
3650         height = skinframe->qheight;
3651         skindata = skinframe->qpixels;
3652
3653         if (skinframe->qgeneratenmap)
3654         {
3655                 unsigned char *temp1, *temp2;
3656                 skinframe->qgeneratenmap = false;
3657                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3658                 temp2 = temp1 + width * height * 4;
3659                 // use either a custom palette or the quake palette
3660                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3661                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3662                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3663                 Mem_Free(temp1);
3664         }
3665
3666         if (skinframe->qgenerateglow)
3667         {
3668                 skinframe->qgenerateglow = false;
3669                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3670         }
3671
3672         if (colormapped)
3673         {
3674                 skinframe->qgeneratebase = false;
3675                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3676                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3677                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3678         }
3679         else
3680         {
3681                 skinframe->qgeneratemerged = false;
3682                 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);
3683         }
3684
3685         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3686         {
3687                 Mem_Free(skinframe->qpixels);
3688                 skinframe->qpixels = NULL;
3689         }
3690 }
3691
3692 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)
3693 {
3694         int i;
3695         skinframe_t *skinframe;
3696         char vabuf[1024];
3697
3698         if (cls.state == ca_dedicated)
3699                 return NULL;
3700
3701         // if already loaded just return it, otherwise make a new skinframe
3702         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3703         if (skinframe && skinframe->base)
3704                 return skinframe;
3705         textureflags &= ~TEXF_FORCE_RELOAD;
3706
3707         skinframe->stain = NULL;
3708         skinframe->merged = NULL;
3709         skinframe->base = NULL;
3710         skinframe->pants = NULL;
3711         skinframe->shirt = NULL;
3712         skinframe->nmap = NULL;
3713         skinframe->gloss = NULL;
3714         skinframe->glow = NULL;
3715         skinframe->fog = NULL;
3716         skinframe->reflect = NULL;
3717         skinframe->hasalpha = false;
3718
3719         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3720         if (!skindata)
3721                 return NULL;
3722
3723         if (developer_loading.integer)
3724                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3725
3726         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3727         if (textureflags & TEXF_ALPHA)
3728         {
3729                 for (i = 0;i < width * height;i++)
3730                 {
3731                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3732                         {
3733                                 skinframe->hasalpha = true;
3734                                 break;
3735                         }
3736                 }
3737                 if (r_loadfog && skinframe->hasalpha)
3738                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3739         }
3740
3741         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3742         //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]);
3743
3744         return skinframe;
3745 }
3746
3747 skinframe_t *R_SkinFrame_LoadMissing(void)
3748 {
3749         skinframe_t *skinframe;
3750
3751         if (cls.state == ca_dedicated)
3752                 return NULL;
3753
3754         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3755         skinframe->stain = NULL;
3756         skinframe->merged = NULL;
3757         skinframe->base = NULL;
3758         skinframe->pants = NULL;
3759         skinframe->shirt = NULL;
3760         skinframe->nmap = NULL;
3761         skinframe->gloss = NULL;
3762         skinframe->glow = NULL;
3763         skinframe->fog = NULL;
3764         skinframe->reflect = NULL;
3765         skinframe->hasalpha = false;
3766
3767         skinframe->avgcolor[0] = rand() / RAND_MAX;
3768         skinframe->avgcolor[1] = rand() / RAND_MAX;
3769         skinframe->avgcolor[2] = rand() / RAND_MAX;
3770         skinframe->avgcolor[3] = 1;
3771
3772         return skinframe;
3773 }
3774
3775 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3776 typedef struct suffixinfo_s
3777 {
3778         const char *suffix;
3779         qboolean flipx, flipy, flipdiagonal;
3780 }
3781 suffixinfo_t;
3782 static suffixinfo_t suffix[3][6] =
3783 {
3784         {
3785                 {"px",   false, false, false},
3786                 {"nx",   false, false, false},
3787                 {"py",   false, false, false},
3788                 {"ny",   false, false, false},
3789                 {"pz",   false, false, false},
3790                 {"nz",   false, false, false}
3791         },
3792         {
3793                 {"posx", false, false, false},
3794                 {"negx", false, false, false},
3795                 {"posy", false, false, false},
3796                 {"negy", false, false, false},
3797                 {"posz", false, false, false},
3798                 {"negz", false, false, false}
3799         },
3800         {
3801                 {"rt",    true, false,  true},
3802                 {"lf",   false,  true,  true},
3803                 {"ft",    true,  true, false},
3804                 {"bk",   false, false, false},
3805                 {"up",    true, false,  true},
3806                 {"dn",    true, false,  true}
3807         }
3808 };
3809
3810 static int componentorder[4] = {0, 1, 2, 3};
3811
3812 static rtexture_t *R_LoadCubemap(const char *basename)
3813 {
3814         int i, j, cubemapsize;
3815         unsigned char *cubemappixels, *image_buffer;
3816         rtexture_t *cubemaptexture;
3817         char name[256];
3818         // must start 0 so the first loadimagepixels has no requested width/height
3819         cubemapsize = 0;
3820         cubemappixels = NULL;
3821         cubemaptexture = NULL;
3822         // keep trying different suffix groups (posx, px, rt) until one loads
3823         for (j = 0;j < 3 && !cubemappixels;j++)
3824         {
3825                 // load the 6 images in the suffix group
3826                 for (i = 0;i < 6;i++)
3827                 {
3828                         // generate an image name based on the base and and suffix
3829                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3830                         // load it
3831                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3832                         {
3833                                 // an image loaded, make sure width and height are equal
3834                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3835                                 {
3836                                         // if this is the first image to load successfully, allocate the cubemap memory
3837                                         if (!cubemappixels && image_width >= 1)
3838                                         {
3839                                                 cubemapsize = image_width;
3840                                                 // note this clears to black, so unavailable sides are black
3841                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3842                                         }
3843                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3844                                         if (cubemappixels)
3845                                                 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);
3846                                 }
3847                                 else
3848                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3849                                 // free the image
3850                                 Mem_Free(image_buffer);
3851                         }
3852                 }
3853         }
3854         // if a cubemap loaded, upload it
3855         if (cubemappixels)
3856         {
3857                 if (developer_loading.integer)
3858                         Con_Printf("loading cubemap \"%s\"\n", basename);
3859
3860                 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);
3861                 Mem_Free(cubemappixels);
3862         }
3863         else
3864         {
3865                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3866                 if (developer_loading.integer)
3867                 {
3868                         Con_Printf("(tried tried images ");
3869                         for (j = 0;j < 3;j++)
3870                                 for (i = 0;i < 6;i++)
3871                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3872                         Con_Print(" and was unable to find any of them).\n");
3873                 }
3874         }
3875         return cubemaptexture;
3876 }
3877
3878 rtexture_t *R_GetCubemap(const char *basename)
3879 {
3880         int i;
3881         for (i = 0;i < r_texture_numcubemaps;i++)
3882                 if (r_texture_cubemaps[i] != NULL)
3883                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3884                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3885         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3886                 return r_texture_whitecube;
3887         r_texture_numcubemaps++;
3888         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3889         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3890         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3891         return r_texture_cubemaps[i]->texture;
3892 }
3893
3894 static void R_Main_FreeViewCache(void)
3895 {
3896         if (r_refdef.viewcache.entityvisible)
3897                 Mem_Free(r_refdef.viewcache.entityvisible);
3898         if (r_refdef.viewcache.world_pvsbits)
3899                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3900         if (r_refdef.viewcache.world_leafvisible)
3901                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3902         if (r_refdef.viewcache.world_surfacevisible)
3903                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3904         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3905 }
3906
3907 static void R_Main_ResizeViewCache(void)
3908 {
3909         int numentities = r_refdef.scene.numentities;
3910         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3911         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3912         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3913         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3914         if (r_refdef.viewcache.maxentities < numentities)
3915         {
3916                 r_refdef.viewcache.maxentities = numentities;
3917                 if (r_refdef.viewcache.entityvisible)
3918                         Mem_Free(r_refdef.viewcache.entityvisible);
3919                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3920         }
3921         if (r_refdef.viewcache.world_numclusters != numclusters)
3922         {
3923                 r_refdef.viewcache.world_numclusters = numclusters;
3924                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3925                 if (r_refdef.viewcache.world_pvsbits)
3926                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3927                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3928         }
3929         if (r_refdef.viewcache.world_numleafs != numleafs)
3930         {
3931                 r_refdef.viewcache.world_numleafs = numleafs;
3932                 if (r_refdef.viewcache.world_leafvisible)
3933                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3934                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3935         }
3936         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3937         {
3938                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3939                 if (r_refdef.viewcache.world_surfacevisible)
3940                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3941                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3942         }
3943 }
3944
3945 extern rtexture_t *loadingscreentexture;
3946 static void gl_main_start(void)
3947 {
3948         loadingscreentexture = NULL;
3949         r_texture_blanknormalmap = NULL;
3950         r_texture_white = NULL;
3951         r_texture_grey128 = NULL;
3952         r_texture_black = NULL;
3953         r_texture_whitecube = NULL;
3954         r_texture_normalizationcube = NULL;
3955         r_texture_fogattenuation = NULL;
3956         r_texture_fogheighttexture = NULL;
3957         r_texture_gammaramps = NULL;
3958         r_texture_numcubemaps = 0;
3959
3960         r_loaddds = r_texture_dds_load.integer != 0;
3961         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3962
3963         switch(vid.renderpath)
3964         {
3965         case RENDERPATH_GL20:
3966         case RENDERPATH_D3D9:
3967         case RENDERPATH_D3D10:
3968         case RENDERPATH_D3D11:
3969         case RENDERPATH_SOFT:
3970         case RENDERPATH_GLES2:
3971                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3972                 Cvar_SetValueQuick(&gl_combine, 1);
3973                 Cvar_SetValueQuick(&r_glsl, 1);
3974                 r_loadnormalmap = true;
3975                 r_loadgloss = true;
3976                 r_loadfog = false;
3977                 break;
3978         case RENDERPATH_GL13:
3979         case RENDERPATH_GLES1:
3980                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3981                 Cvar_SetValueQuick(&gl_combine, 1);
3982                 Cvar_SetValueQuick(&r_glsl, 0);
3983                 r_loadnormalmap = false;
3984                 r_loadgloss = false;
3985                 r_loadfog = true;
3986                 break;
3987         case RENDERPATH_GL11:
3988                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3989                 Cvar_SetValueQuick(&gl_combine, 0);
3990                 Cvar_SetValueQuick(&r_glsl, 0);
3991                 r_loadnormalmap = false;
3992                 r_loadgloss = false;
3993                 r_loadfog = true;
3994                 break;
3995         }
3996
3997         R_AnimCache_Free();
3998         R_FrameData_Reset();
3999
4000         r_numqueries = 0;
4001         r_maxqueries = 0;
4002         memset(r_queries, 0, sizeof(r_queries));
4003
4004         r_qwskincache = NULL;
4005         r_qwskincache_size = 0;
4006
4007         // due to caching of texture_t references, the collision cache must be reset
4008         Collision_Cache_Reset(true);
4009
4010         // set up r_skinframe loading system for textures
4011         memset(&r_skinframe, 0, sizeof(r_skinframe));
4012         r_skinframe.loadsequence = 1;
4013         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4014
4015         r_main_texturepool = R_AllocTexturePool();
4016         R_BuildBlankTextures();
4017         R_BuildNoTexture();
4018         if (vid.support.arb_texture_cube_map)
4019         {
4020                 R_BuildWhiteCube();
4021                 R_BuildNormalizationCube();
4022         }
4023         r_texture_fogattenuation = NULL;
4024         r_texture_fogheighttexture = NULL;
4025         r_texture_gammaramps = NULL;
4026         //r_texture_fogintensity = NULL;
4027         memset(&r_fb, 0, sizeof(r_fb));
4028         r_glsl_permutation = NULL;
4029         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4030         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4031         glslshaderstring = NULL;
4032 #ifdef SUPPORTD3D
4033         r_hlsl_permutation = NULL;
4034         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4035         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4036 #endif
4037         hlslshaderstring = NULL;
4038         memset(&r_svbsp, 0, sizeof (r_svbsp));
4039
4040         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4041         r_texture_numcubemaps = 0;
4042
4043         r_refdef.fogmasktable_density = 0;
4044 }
4045
4046 static void gl_main_shutdown(void)
4047 {
4048         R_AnimCache_Free();
4049         R_FrameData_Reset();
4050
4051         R_Main_FreeViewCache();
4052
4053         switch(vid.renderpath)
4054         {
4055         case RENDERPATH_GL11:
4056         case RENDERPATH_GL13:
4057         case RENDERPATH_GL20:
4058         case RENDERPATH_GLES1:
4059         case RENDERPATH_GLES2:
4060 #ifdef GL_SAMPLES_PASSED_ARB
4061                 if (r_maxqueries)
4062                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4063 #endif
4064                 break;
4065         case RENDERPATH_D3D9:
4066                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4067                 break;
4068         case RENDERPATH_D3D10:
4069                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4070                 break;
4071         case RENDERPATH_D3D11:
4072                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4073                 break;
4074         case RENDERPATH_SOFT:
4075                 break;
4076         }
4077
4078         r_numqueries = 0;
4079         r_maxqueries = 0;
4080         memset(r_queries, 0, sizeof(r_queries));
4081
4082         r_qwskincache = NULL;
4083         r_qwskincache_size = 0;
4084
4085         // clear out the r_skinframe state
4086         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4087         memset(&r_skinframe, 0, sizeof(r_skinframe));
4088
4089         if (r_svbsp.nodes)
4090                 Mem_Free(r_svbsp.nodes);
4091         memset(&r_svbsp, 0, sizeof (r_svbsp));
4092         R_FreeTexturePool(&r_main_texturepool);
4093         loadingscreentexture = NULL;
4094         r_texture_blanknormalmap = NULL;
4095         r_texture_white = NULL;
4096         r_texture_grey128 = NULL;
4097         r_texture_black = NULL;
4098         r_texture_whitecube = NULL;
4099         r_texture_normalizationcube = NULL;
4100         r_texture_fogattenuation = NULL;
4101         r_texture_fogheighttexture = NULL;
4102         r_texture_gammaramps = NULL;
4103         r_texture_numcubemaps = 0;
4104         //r_texture_fogintensity = NULL;
4105         memset(&r_fb, 0, sizeof(r_fb));
4106         R_GLSL_Restart_f();
4107
4108         r_glsl_permutation = NULL;
4109         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4110         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4111         glslshaderstring = NULL;
4112 #ifdef SUPPORTD3D
4113         r_hlsl_permutation = NULL;
4114         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4115         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4116 #endif
4117         hlslshaderstring = NULL;
4118 }
4119
4120 static void gl_main_newmap(void)
4121 {
4122         // FIXME: move this code to client
4123         char *entities, entname[MAX_QPATH];
4124         if (r_qwskincache)
4125                 Mem_Free(r_qwskincache);
4126         r_qwskincache = NULL;
4127         r_qwskincache_size = 0;
4128         if (cl.worldmodel)
4129         {
4130                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4131                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4132                 {
4133                         CL_ParseEntityLump(entities);
4134                         Mem_Free(entities);
4135                         return;
4136                 }
4137                 if (cl.worldmodel->brush.entities)
4138                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4139         }
4140         R_Main_FreeViewCache();
4141
4142         R_FrameData_Reset();
4143 }
4144
4145 void GL_Main_Init(void)
4146 {
4147         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4148
4149         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4150         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4151         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4152         if (gamemode == GAME_NEHAHRA)
4153         {
4154                 Cvar_RegisterVariable (&gl_fogenable);
4155                 Cvar_RegisterVariable (&gl_fogdensity);
4156                 Cvar_RegisterVariable (&gl_fogred);
4157                 Cvar_RegisterVariable (&gl_foggreen);
4158                 Cvar_RegisterVariable (&gl_fogblue);
4159                 Cvar_RegisterVariable (&gl_fogstart);
4160                 Cvar_RegisterVariable (&gl_fogend);
4161                 Cvar_RegisterVariable (&gl_skyclip);
4162         }
4163         Cvar_RegisterVariable(&r_motionblur);
4164         Cvar_RegisterVariable(&r_damageblur);
4165         Cvar_RegisterVariable(&r_motionblur_averaging);
4166         Cvar_RegisterVariable(&r_motionblur_randomize);
4167         Cvar_RegisterVariable(&r_motionblur_minblur);
4168         Cvar_RegisterVariable(&r_motionblur_maxblur);
4169         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4170         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4171         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4172         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4173         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4174         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4175         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4176         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4177         Cvar_RegisterVariable(&r_equalize_entities_by);
4178         Cvar_RegisterVariable(&r_equalize_entities_to);
4179         Cvar_RegisterVariable(&r_depthfirst);
4180         Cvar_RegisterVariable(&r_useinfinitefarclip);
4181         Cvar_RegisterVariable(&r_farclip_base);
4182         Cvar_RegisterVariable(&r_farclip_world);
4183         Cvar_RegisterVariable(&r_nearclip);
4184         Cvar_RegisterVariable(&r_deformvertexes);
4185         Cvar_RegisterVariable(&r_transparent);
4186         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4187         Cvar_RegisterVariable(&r_showoverdraw);
4188         Cvar_RegisterVariable(&r_showbboxes);
4189         Cvar_RegisterVariable(&r_showsurfaces);
4190         Cvar_RegisterVariable(&r_showtris);
4191         Cvar_RegisterVariable(&r_shownormals);
4192         Cvar_RegisterVariable(&r_showlighting);
4193         Cvar_RegisterVariable(&r_showshadowvolumes);
4194         Cvar_RegisterVariable(&r_showcollisionbrushes);
4195         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4196         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4197         Cvar_RegisterVariable(&r_showdisabledepthtest);
4198         Cvar_RegisterVariable(&r_drawportals);
4199         Cvar_RegisterVariable(&r_drawentities);
4200         Cvar_RegisterVariable(&r_draw2d);
4201         Cvar_RegisterVariable(&r_drawworld);
4202         Cvar_RegisterVariable(&r_cullentities_trace);
4203         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4204         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4205         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4206         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4207         Cvar_RegisterVariable(&r_sortentities);
4208         Cvar_RegisterVariable(&r_drawviewmodel);
4209         Cvar_RegisterVariable(&r_drawexteriormodel);
4210         Cvar_RegisterVariable(&r_speeds);
4211         Cvar_RegisterVariable(&r_fullbrights);
4212         Cvar_RegisterVariable(&r_wateralpha);
4213         Cvar_RegisterVariable(&r_dynamic);
4214         Cvar_RegisterVariable(&r_fakelight);
4215         Cvar_RegisterVariable(&r_fakelight_intensity);
4216         Cvar_RegisterVariable(&r_fullbright);
4217         Cvar_RegisterVariable(&r_shadows);
4218         Cvar_RegisterVariable(&r_shadows_darken);
4219         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4220         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4221         Cvar_RegisterVariable(&r_shadows_throwdistance);
4222         Cvar_RegisterVariable(&r_shadows_throwdirection);
4223         Cvar_RegisterVariable(&r_shadows_focus);
4224         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4225         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4226         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4227         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4228         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4229         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4230         Cvar_RegisterVariable(&r_fog_exp2);
4231         Cvar_RegisterVariable(&r_fog_clear);
4232         Cvar_RegisterVariable(&r_drawfog);
4233         Cvar_RegisterVariable(&r_transparentdepthmasking);
4234         Cvar_RegisterVariable(&r_transparent_sortmindist);
4235         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4236         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4237         Cvar_RegisterVariable(&r_texture_dds_load);
4238         Cvar_RegisterVariable(&r_texture_dds_save);
4239         Cvar_RegisterVariable(&r_textureunits);
4240         Cvar_RegisterVariable(&gl_combine);
4241         Cvar_RegisterVariable(&r_viewfbo);
4242         Cvar_RegisterVariable(&r_viewscale);
4243         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4244         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4245         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4246         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4247         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4248         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4249         Cvar_RegisterVariable(&r_glsl);
4250         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4251         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4252         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4253         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4254         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4255         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4256         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4257         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4258         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4259         Cvar_RegisterVariable(&r_glsl_postprocess);
4260         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4261         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4262         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4263         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4264         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4265         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4266         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4267         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4268
4269         Cvar_RegisterVariable(&r_water);
4270         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4271         Cvar_RegisterVariable(&r_water_clippingplanebias);
4272         Cvar_RegisterVariable(&r_water_refractdistort);
4273         Cvar_RegisterVariable(&r_water_reflectdistort);
4274         Cvar_RegisterVariable(&r_water_scissormode);
4275         Cvar_RegisterVariable(&r_water_lowquality);
4276         Cvar_RegisterVariable(&r_water_hideplayer);
4277         Cvar_RegisterVariable(&r_water_fbo);
4278
4279         Cvar_RegisterVariable(&r_lerpsprites);
4280         Cvar_RegisterVariable(&r_lerpmodels);
4281         Cvar_RegisterVariable(&r_lerplightstyles);
4282         Cvar_RegisterVariable(&r_waterscroll);
4283         Cvar_RegisterVariable(&r_bloom);
4284         Cvar_RegisterVariable(&r_bloom_colorscale);
4285         Cvar_RegisterVariable(&r_bloom_brighten);
4286         Cvar_RegisterVariable(&r_bloom_blur);
4287         Cvar_RegisterVariable(&r_bloom_resolution);
4288         Cvar_RegisterVariable(&r_bloom_colorexponent);
4289         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4290         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4291         Cvar_RegisterVariable(&r_hdr_glowintensity);
4292         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4293         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4294         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4295         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4296         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4297         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4298         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4299         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4300         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4301         Cvar_RegisterVariable(&developer_texturelogging);
4302         Cvar_RegisterVariable(&gl_lightmaps);
4303         Cvar_RegisterVariable(&r_test);
4304         Cvar_RegisterVariable(&r_glsl_saturation);
4305         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4306         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4307         Cvar_RegisterVariable(&r_framedatasize);
4308         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4309                 Cvar_SetValue("r_fullbrights", 0);
4310         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4311 }
4312
4313 void Render_Init(void)
4314 {
4315         gl_backend_init();
4316         R_Textures_Init();
4317         GL_Main_Init();
4318         Font_Init();
4319         GL_Draw_Init();
4320         R_Shadow_Init();
4321         R_Sky_Init();
4322         GL_Surf_Init();
4323         Sbar_Init();
4324         R_Particles_Init();
4325         R_Explosion_Init();
4326         R_LightningBeams_Init();
4327         Mod_RenderInit();
4328 }
4329
4330 /*
4331 ===============
4332 GL_Init
4333 ===============
4334 */
4335 #ifndef USE_GLES2
4336 extern char *ENGINE_EXTENSIONS;
4337 void GL_Init (void)
4338 {
4339         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4340         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4341         gl_version = (const char *)qglGetString(GL_VERSION);
4342         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4343
4344         if (!gl_extensions)
4345                 gl_extensions = "";
4346         if (!gl_platformextensions)
4347                 gl_platformextensions = "";
4348
4349         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4350         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4351         Con_Printf("GL_VERSION: %s\n", gl_version);
4352         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4353         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4354
4355         VID_CheckExtensions();
4356
4357         // LordHavoc: report supported extensions
4358         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4359
4360         // clear to black (loading plaque will be seen over this)
4361         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4362 }
4363 #endif
4364
4365 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4366 {
4367         int i;
4368         mplane_t *p;
4369         if (r_trippy.integer)
4370                 return false;
4371         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4372         {
4373                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4374                 if (i == 4)
4375                         continue;
4376                 p = r_refdef.view.frustum + i;
4377                 switch(p->signbits)
4378                 {
4379                 default:
4380                 case 0:
4381                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4382                                 return true;
4383                         break;
4384                 case 1:
4385                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4386                                 return true;
4387                         break;
4388                 case 2:
4389                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4390                                 return true;
4391                         break;
4392                 case 3:
4393                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4394                                 return true;
4395                         break;
4396                 case 4:
4397                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4398                                 return true;
4399                         break;
4400                 case 5:
4401                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4402                                 return true;
4403                         break;
4404                 case 6:
4405                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4406                                 return true;
4407                         break;
4408                 case 7:
4409                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4410                                 return true;
4411                         break;
4412                 }
4413         }
4414         return false;
4415 }
4416
4417 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4418 {
4419         int i;
4420         const mplane_t *p;
4421         if (r_trippy.integer)
4422                 return false;
4423         for (i = 0;i < numplanes;i++)
4424         {
4425                 p = planes + i;
4426                 switch(p->signbits)
4427                 {
4428                 default:
4429                 case 0:
4430                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 1:
4434                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 2:
4438                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 3:
4442                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 4:
4446                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 5:
4450                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 6:
4454                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 7:
4458                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 }
4462         }
4463         return false;
4464 }
4465
4466 //==================================================================================
4467
4468 // LordHavoc: this stores temporary data used within the same frame
4469
4470 typedef struct r_framedata_mem_s
4471 {
4472         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4473         size_t size; // how much usable space
4474         size_t current; // how much space in use
4475         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4476         size_t wantedsize; // how much space was allocated
4477         unsigned char *data; // start of real data (16byte aligned)
4478 }
4479 r_framedata_mem_t;
4480
4481 static r_framedata_mem_t *r_framedata_mem;
4482
4483 void R_FrameData_Reset(void)
4484 {
4485         while (r_framedata_mem)
4486         {
4487                 r_framedata_mem_t *next = r_framedata_mem->purge;
4488                 Mem_Free(r_framedata_mem);
4489                 r_framedata_mem = next;
4490         }
4491 }
4492
4493 static void R_FrameData_Resize(void)
4494 {
4495         size_t wantedsize;
4496         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4497         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4498         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4499         {
4500                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4501                 newmem->wantedsize = wantedsize;
4502                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4503                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4504                 newmem->current = 0;
4505                 newmem->mark = 0;
4506                 newmem->purge = r_framedata_mem;
4507                 r_framedata_mem = newmem;
4508         }
4509 }
4510
4511 void R_FrameData_NewFrame(void)
4512 {
4513         R_FrameData_Resize();
4514         if (!r_framedata_mem)
4515                 return;
4516         // if we ran out of space on the last frame, free the old memory now
4517         while (r_framedata_mem->purge)
4518         {
4519                 // repeatedly remove the second item in the list, leaving only head
4520                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4521                 Mem_Free(r_framedata_mem->purge);
4522                 r_framedata_mem->purge = next;
4523         }
4524         // reset the current mem pointer
4525         r_framedata_mem->current = 0;
4526         r_framedata_mem->mark = 0;
4527 }
4528
4529 void *R_FrameData_Alloc(size_t size)
4530 {
4531         void *data;
4532
4533         // align to 16 byte boundary - the data pointer is already aligned, so we
4534         // only need to ensure the size of every allocation is also aligned
4535         size = (size + 15) & ~15;
4536
4537         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4538         {
4539                 // emergency - we ran out of space, allocate more memory
4540                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4541                 R_FrameData_Resize();
4542         }
4543
4544         data = r_framedata_mem->data + r_framedata_mem->current;
4545         r_framedata_mem->current += size;
4546
4547         // count the usage for stats
4548         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4549         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4550
4551         return (void *)data;
4552 }
4553
4554 void *R_FrameData_Store(size_t size, void *data)
4555 {
4556         void *d = R_FrameData_Alloc(size);
4557         if (d && data)
4558                 memcpy(d, data, size);
4559         return d;
4560 }
4561
4562 void R_FrameData_SetMark(void)
4563 {
4564         if (!r_framedata_mem)
4565                 return;
4566         r_framedata_mem->mark = r_framedata_mem->current;
4567 }
4568
4569 void R_FrameData_ReturnToMark(void)
4570 {
4571         if (!r_framedata_mem)
4572                 return;
4573         r_framedata_mem->current = r_framedata_mem->mark;
4574 }
4575
4576 //==================================================================================
4577
4578 // LordHavoc: animcache originally written by Echon, rewritten since then
4579
4580 /**
4581  * Animation cache prevents re-generating mesh data for an animated model
4582  * multiple times in one frame for lighting, shadowing, reflections, etc.
4583  */
4584
4585 void R_AnimCache_Free(void)
4586 {
4587 }
4588
4589 void R_AnimCache_ClearCache(void)
4590 {
4591         int i;
4592         entity_render_t *ent;
4593
4594         for (i = 0;i < r_refdef.scene.numentities;i++)
4595         {
4596                 ent = r_refdef.scene.entities[i];
4597                 ent->animcache_vertex3f = NULL;
4598                 ent->animcache_normal3f = NULL;
4599                 ent->animcache_svector3f = NULL;
4600                 ent->animcache_tvector3f = NULL;
4601                 ent->animcache_vertexmesh = NULL;
4602                 ent->animcache_vertex3fbuffer = NULL;
4603                 ent->animcache_vertexmeshbuffer = NULL;
4604         }
4605 }
4606
4607 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4608 {
4609         int i;
4610
4611         // check if we need the meshbuffers
4612         if (!vid.useinterleavedarrays)
4613                 return;
4614
4615         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4616                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4617         // TODO: upload vertex3f buffer?
4618         if (ent->animcache_vertexmesh)
4619         {
4620                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4621                 for (i = 0;i < numvertices;i++)
4622                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4623                 if (ent->animcache_svector3f)
4624                         for (i = 0;i < numvertices;i++)
4625                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4626                 if (ent->animcache_tvector3f)
4627                         for (i = 0;i < numvertices;i++)
4628                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4629                 if (ent->animcache_normal3f)
4630                         for (i = 0;i < numvertices;i++)
4631                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4632                 // TODO: upload vertexmeshbuffer?
4633         }
4634 }
4635
4636 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4637 {
4638         dp_model_t *model = ent->model;
4639         int numvertices;
4640         // see if it's already cached this frame
4641         if (ent->animcache_vertex3f)
4642         {
4643                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4644                 if (wantnormals || wanttangents)
4645                 {
4646                         if (ent->animcache_normal3f)
4647                                 wantnormals = false;
4648                         if (ent->animcache_svector3f)
4649                                 wanttangents = false;
4650                         if (wantnormals || wanttangents)
4651                         {
4652                                 numvertices = model->surfmesh.num_vertices;
4653                                 if (wantnormals)
4654                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4655                                 if (wanttangents)
4656                                 {
4657                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4658                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4659                                 }
4660                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4661                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4662                         }
4663                 }
4664         }
4665         else
4666         {
4667                 // see if this ent is worth caching
4668                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4669                         return false;
4670                 // get some memory for this entity and generate mesh data
4671                 numvertices = model->surfmesh.num_vertices;
4672                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4673                 if (wantnormals)
4674                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4675                 if (wanttangents)
4676                 {
4677                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4678                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4679                 }
4680                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4681                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4682         }
4683         return true;
4684 }
4685
4686 void R_AnimCache_CacheVisibleEntities(void)
4687 {
4688         int i;
4689         qboolean wantnormals = true;
4690         qboolean wanttangents = !r_showsurfaces.integer;
4691
4692         switch(vid.renderpath)
4693         {
4694         case RENDERPATH_GL20:
4695         case RENDERPATH_D3D9:
4696         case RENDERPATH_D3D10:
4697         case RENDERPATH_D3D11:
4698         case RENDERPATH_GLES2:
4699                 break;
4700         case RENDERPATH_GL11:
4701         case RENDERPATH_GL13:
4702         case RENDERPATH_GLES1:
4703                 wanttangents = false;
4704                 break;
4705         case RENDERPATH_SOFT:
4706                 break;
4707         }
4708
4709         if (r_shownormals.integer)
4710                 wanttangents = wantnormals = true;
4711
4712         // TODO: thread this
4713         // NOTE: R_PrepareRTLights() also caches entities
4714
4715         for (i = 0;i < r_refdef.scene.numentities;i++)
4716                 if (r_refdef.viewcache.entityvisible[i])
4717                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4718 }
4719
4720 //==================================================================================
4721
4722 extern cvar_t r_overheadsprites_pushback;
4723
4724 static void R_View_UpdateEntityLighting (void)
4725 {
4726         int i;
4727         entity_render_t *ent;
4728         vec3_t tempdiffusenormal, avg;
4729         vec_t f, fa, fd, fdd;
4730         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4731
4732         for (i = 0;i < r_refdef.scene.numentities;i++)
4733         {
4734                 ent = r_refdef.scene.entities[i];
4735
4736                 // skip unseen models and models that updated by CSQC
4737                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4738                         continue;
4739
4740                 // skip bsp models
4741                 if (ent->model && ent->model->brush.num_leafs)
4742                 {
4743                         // TODO: use modellight for r_ambient settings on world?
4744                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4745                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4746                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4747                         continue;
4748                 }
4749
4750                 // fetch the lighting from the worldmodel data
4751                 VectorClear(ent->modellight_ambient);
4752                 VectorClear(ent->modellight_diffuse);
4753                 VectorClear(tempdiffusenormal);
4754                 if (ent->flags & RENDER_LIGHT)
4755                 {
4756                         vec3_t org;
4757                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4758
4759                         // complete lightning for lit sprites
4760                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4761                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4762                         {
4763                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4764                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4765                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4766                         }
4767                         else
4768                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4769
4770                         if(ent->flags & RENDER_EQUALIZE)
4771                         {
4772                                 // first fix up ambient lighting...
4773                                 if(r_equalize_entities_minambient.value > 0)
4774                                 {
4775                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4776                                         if(fd > 0)
4777                                         {
4778                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4779                                                 if(fa < r_equalize_entities_minambient.value * fd)
4780                                                 {
4781                                                         // solve:
4782                                                         //   fa'/fd' = minambient
4783                                                         //   fa'+0.25*fd' = fa+0.25*fd
4784                                                         //   ...
4785                                                         //   fa' = fd' * minambient
4786                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4787                                                         //   ...
4788                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4789                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4790                                                         //   ...
4791                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4792                                                         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
4793                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4794                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4795                                                 }
4796                                         }
4797                                 }
4798
4799                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4800                                 {
4801                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4802                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4803                                         f = fa + 0.25 * fd;
4804                                         if(f > 0)
4805                                         {
4806                                                 // adjust brightness and saturation to target
4807                                                 avg[0] = avg[1] = avg[2] = fa / f;
4808                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4809                                                 avg[0] = avg[1] = avg[2] = fd / f;
4810                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4811                                         }
4812                                 }
4813                         }
4814                 }
4815                 else // highly rare
4816                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4817
4818                 // move the light direction into modelspace coordinates for lighting code
4819                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4820                 if(VectorLength2(ent->modellight_lightdir) == 0)
4821                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4822                 VectorNormalize(ent->modellight_lightdir);
4823         }
4824 }
4825
4826 #define MAX_LINEOFSIGHTTRACES 64
4827
4828 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4829 {
4830         int i;
4831         vec3_t boxmins, boxmaxs;
4832         vec3_t start;
4833         vec3_t end;
4834         dp_model_t *model = r_refdef.scene.worldmodel;
4835
4836         if (!model || !model->brush.TraceLineOfSight)
4837                 return true;
4838
4839         // expand the box a little
4840         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4841         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4842         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4843         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4844         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4845         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4846
4847         // return true if eye is inside enlarged box
4848         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4849                 return true;
4850
4851         // try center
4852         VectorCopy(eye, start);
4853         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4854         if (model->brush.TraceLineOfSight(model, start, end))
4855                 return true;
4856
4857         // try various random positions
4858         for (i = 0;i < numsamples;i++)
4859         {
4860                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4861                 if (model->brush.TraceLineOfSight(model, start, end))
4862                         return true;
4863         }
4864
4865         return false;
4866 }
4867
4868
4869 static void R_View_UpdateEntityVisible (void)
4870 {
4871         int i;
4872         int renderimask;
4873         int samples;
4874         entity_render_t *ent;
4875
4876         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4877                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4878                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4879                 :                                                          RENDER_EXTERIORMODEL;
4880         if (!r_drawviewmodel.integer)
4881                 renderimask |= RENDER_VIEWMODEL;
4882         if (!r_drawexteriormodel.integer)
4883                 renderimask |= RENDER_EXTERIORMODEL;
4884         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4885         {
4886                 // worldmodel can check visibility
4887                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4888                 for (i = 0;i < r_refdef.scene.numentities;i++)
4889                 {
4890                         ent = r_refdef.scene.entities[i];
4891                         if (!(ent->flags & renderimask))
4892                         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)))
4893                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4894                                 r_refdef.viewcache.entityvisible[i] = true;
4895                 }
4896         }
4897         else
4898         {
4899                 // no worldmodel or it can't check visibility
4900                 for (i = 0;i < r_refdef.scene.numentities;i++)
4901                 {
4902                         ent = r_refdef.scene.entities[i];
4903                         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));
4904                 }
4905         }
4906         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4907                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4908         {
4909                 for (i = 0;i < r_refdef.scene.numentities;i++)
4910                 {
4911                         if (!r_refdef.viewcache.entityvisible[i])
4912                                 continue;
4913                         ent = r_refdef.scene.entities[i];
4914                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4915                         {
4916                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4917                                 if (samples < 0)
4918                                         continue; // temp entities do pvs only
4919                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4920                                         ent->last_trace_visibility = realtime;
4921                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4922                                         r_refdef.viewcache.entityvisible[i] = 0;
4923                         }
4924                 }
4925         }
4926 }
4927
4928 /// only used if skyrendermasked, and normally returns false
4929 static int R_DrawBrushModelsSky (void)
4930 {
4931         int i, sky;
4932         entity_render_t *ent;
4933
4934         sky = false;
4935         for (i = 0;i < r_refdef.scene.numentities;i++)
4936         {
4937                 if (!r_refdef.viewcache.entityvisible[i])
4938                         continue;
4939                 ent = r_refdef.scene.entities[i];
4940                 if (!ent->model || !ent->model->DrawSky)
4941                         continue;
4942                 ent->model->DrawSky(ent);
4943                 sky = true;
4944         }
4945         return sky;
4946 }
4947
4948 static void R_DrawNoModel(entity_render_t *ent);
4949 static void R_DrawModels(void)
4950 {
4951         int i;
4952         entity_render_t *ent;
4953
4954         for (i = 0;i < r_refdef.scene.numentities;i++)
4955         {
4956                 if (!r_refdef.viewcache.entityvisible[i])
4957                         continue;
4958                 ent = r_refdef.scene.entities[i];
4959                 r_refdef.stats.entities++;
4960                 /*
4961                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4962                 {
4963                         vec3_t f, l, u, o;
4964                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4965                         Con_Printf("R_DrawModels\n");
4966                         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]);
4967                         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);
4968                         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);
4969                 }
4970                 */
4971                 if (ent->model && ent->model->Draw != NULL)
4972                         ent->model->Draw(ent);
4973                 else
4974                         R_DrawNoModel(ent);
4975         }
4976 }
4977
4978 static void R_DrawModelsDepth(void)
4979 {
4980         int i;
4981         entity_render_t *ent;
4982
4983         for (i = 0;i < r_refdef.scene.numentities;i++)
4984         {
4985                 if (!r_refdef.viewcache.entityvisible[i])
4986                         continue;
4987                 ent = r_refdef.scene.entities[i];
4988                 if (ent->model && ent->model->DrawDepth != NULL)
4989                         ent->model->DrawDepth(ent);
4990         }
4991 }
4992
4993 static void R_DrawModelsDebug(void)
4994 {
4995         int i;
4996         entity_render_t *ent;
4997
4998         for (i = 0;i < r_refdef.scene.numentities;i++)
4999         {
5000                 if (!r_refdef.viewcache.entityvisible[i])
5001                         continue;
5002                 ent = r_refdef.scene.entities[i];
5003                 if (ent->model && ent->model->DrawDebug != NULL)
5004                         ent->model->DrawDebug(ent);
5005         }
5006 }
5007
5008 static void R_DrawModelsAddWaterPlanes(void)
5009 {
5010         int i;
5011         entity_render_t *ent;
5012
5013         for (i = 0;i < r_refdef.scene.numentities;i++)
5014         {
5015                 if (!r_refdef.viewcache.entityvisible[i])
5016                         continue;
5017                 ent = r_refdef.scene.entities[i];
5018                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5019                         ent->model->DrawAddWaterPlanes(ent);
5020         }
5021 }
5022
5023 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5024
5025 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5026 {
5027         if (r_hdr_irisadaptation.integer)
5028         {
5029                 vec3_t p;
5030                 vec3_t ambient;
5031                 vec3_t diffuse;
5032                 vec3_t diffusenormal;
5033                 vec3_t forward;
5034                 vec_t brightness = 0.0f;
5035                 vec_t goal;
5036                 vec_t current;
5037                 vec_t d;
5038                 int c;
5039                 VectorCopy(r_refdef.view.forward, forward);
5040                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5041                 {
5042                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5043                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5044                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5045                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5046                         d = DotProduct(forward, diffusenormal);
5047                         brightness += VectorLength(ambient);
5048                         if (d > 0)
5049                                 brightness += d * VectorLength(diffuse);
5050                 }
5051                 brightness *= 1.0f / c;
5052                 brightness += 0.00001f; // make sure it's never zero
5053                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5054                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5055                 current = r_hdr_irisadaptation_value.value;
5056                 if (current < goal)
5057                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5058                 else if (current > goal)
5059                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5060                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5061                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5062         }
5063         else if (r_hdr_irisadaptation_value.value != 1.0f)
5064                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5065 }
5066
5067 static void R_View_SetFrustum(const int *scissor)
5068 {
5069         int i;
5070         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5071         vec3_t forward, left, up, origin, v;
5072
5073         if(scissor)
5074         {
5075                 // flipped x coordinates (because x points left here)
5076                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5077                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5078
5079                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5080                 switch(vid.renderpath)
5081                 {
5082                         case RENDERPATH_D3D9:
5083                         case RENDERPATH_D3D10:
5084                         case RENDERPATH_D3D11:
5085                                 // non-flipped y coordinates
5086                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5087                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5088                                 break;
5089                         case RENDERPATH_SOFT:
5090                         case RENDERPATH_GL11:
5091                         case RENDERPATH_GL13:
5092                         case RENDERPATH_GL20:
5093                         case RENDERPATH_GLES1:
5094                         case RENDERPATH_GLES2:
5095                                 // non-flipped y coordinates
5096                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5097                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5098                                 break;
5099                 }
5100         }
5101
5102         // we can't trust r_refdef.view.forward and friends in reflected scenes
5103         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5104
5105 #if 0
5106         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5107         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5108         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5109         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5110         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5111         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5112         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5113         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5114         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5115         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5116         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5117         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5118 #endif
5119
5120 #if 0
5121         zNear = r_refdef.nearclip;
5122         nudge = 1.0 - 1.0 / (1<<23);
5123         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5124         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5125         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5126         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5127         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5128         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5129         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5130         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5131 #endif
5132
5133
5134
5135 #if 0
5136         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5137         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5138         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5139         r_refdef.view.frustum[0].dist = m[15] - m[12];
5140
5141         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5142         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5143         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5144         r_refdef.view.frustum[1].dist = m[15] + m[12];
5145
5146         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5147         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5148         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5149         r_refdef.view.frustum[2].dist = m[15] - m[13];
5150
5151         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5152         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5153         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5154         r_refdef.view.frustum[3].dist = m[15] + m[13];
5155
5156         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5157         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5158         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5159         r_refdef.view.frustum[4].dist = m[15] - m[14];
5160
5161         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5162         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5163         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5164         r_refdef.view.frustum[5].dist = m[15] + m[14];
5165 #endif
5166
5167         if (r_refdef.view.useperspective)
5168         {
5169                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5170                 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]);
5171                 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]);
5172                 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]);
5173                 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]);
5174
5175                 // then the normals from the corners relative to origin
5176                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5177                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5178                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5179                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5180
5181                 // in a NORMAL view, forward cross left == up
5182                 // in a REFLECTED view, forward cross left == down
5183                 // so our cross products above need to be adjusted for a left handed coordinate system
5184                 CrossProduct(forward, left, v);
5185                 if(DotProduct(v, up) < 0)
5186                 {
5187                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5188                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5189                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5190                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5191                 }
5192
5193                 // Leaving those out was a mistake, those were in the old code, and they
5194                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5195                 // I couldn't reproduce it after adding those normalizations. --blub
5196                 VectorNormalize(r_refdef.view.frustum[0].normal);
5197                 VectorNormalize(r_refdef.view.frustum[1].normal);
5198                 VectorNormalize(r_refdef.view.frustum[2].normal);
5199                 VectorNormalize(r_refdef.view.frustum[3].normal);
5200
5201                 // make the corners absolute
5202                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5203                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5204                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5205                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5206
5207                 // one more normal
5208                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5209
5210                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5211                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5212                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5213                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5214                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5215         }
5216         else
5217         {
5218                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5219                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5220                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5221                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5222                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5223                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5224                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5225                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5226                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5227                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5228         }
5229         r_refdef.view.numfrustumplanes = 5;
5230
5231         if (r_refdef.view.useclipplane)
5232         {
5233                 r_refdef.view.numfrustumplanes = 6;
5234                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5235         }
5236
5237         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5238                 PlaneClassify(r_refdef.view.frustum + i);
5239
5240         // LordHavoc: note to all quake engine coders, Quake had a special case
5241         // for 90 degrees which assumed a square view (wrong), so I removed it,
5242         // Quake2 has it disabled as well.
5243
5244         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5245         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5246         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5247         //PlaneClassify(&frustum[0]);
5248
5249         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5250         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5251         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5252         //PlaneClassify(&frustum[1]);
5253
5254         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5255         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5256         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5257         //PlaneClassify(&frustum[2]);
5258
5259         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5260         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5261         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5262         //PlaneClassify(&frustum[3]);
5263
5264         // nearclip plane
5265         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5266         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5267         //PlaneClassify(&frustum[4]);
5268 }
5269
5270 static void R_View_UpdateWithScissor(const int *myscissor)
5271 {
5272         R_Main_ResizeViewCache();
5273         R_View_SetFrustum(myscissor);
5274         R_View_WorldVisibility(r_refdef.view.useclipplane);
5275         R_View_UpdateEntityVisible();
5276         R_View_UpdateEntityLighting();
5277         R_AnimCache_CacheVisibleEntities();
5278 }
5279
5280 static void R_View_Update(void)
5281 {
5282         R_Main_ResizeViewCache();
5283         R_View_SetFrustum(NULL);
5284         R_View_WorldVisibility(r_refdef.view.useclipplane);
5285         R_View_UpdateEntityVisible();
5286         R_View_UpdateEntityLighting();
5287         R_AnimCache_CacheVisibleEntities();
5288 }
5289
5290 float viewscalefpsadjusted = 1.0f;
5291
5292 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5293 {
5294         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5295         scale = bound(0.03125f, scale, 1.0f);
5296         *outwidth = (int)ceil(width * scale);
5297         *outheight = (int)ceil(height * scale);
5298 }
5299
5300 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5301 {
5302         const float *customclipplane = NULL;
5303         float plane[4];
5304         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5305         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5306         {
5307                 // LordHavoc: couldn't figure out how to make this approach the
5308                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5309                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5310                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5311                         dist = r_refdef.view.clipplane.dist;
5312                 plane[0] = r_refdef.view.clipplane.normal[0];
5313                 plane[1] = r_refdef.view.clipplane.normal[1];
5314                 plane[2] = r_refdef.view.clipplane.normal[2];
5315                 plane[3] = -dist;
5316                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5317         }
5318
5319         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5320         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5321
5322         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5323         if (!r_refdef.view.useperspective)
5324                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - 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);
5325         else if (vid.stencil && r_useinfinitefarclip.integer)
5326                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5327         else
5328                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5329         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5330         R_SetViewport(&r_refdef.view.viewport);
5331         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5332         {
5333                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5334                 float screenplane[4];
5335                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5336                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5337                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5338                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5339                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5340         }
5341 }
5342
5343 void R_EntityMatrix(const matrix4x4_t *matrix)
5344 {
5345         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5346         {
5347                 gl_modelmatrixchanged = false;
5348                 gl_modelmatrix = *matrix;
5349                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5350                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5351                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5352                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5353                 CHECKGLERROR
5354                 switch(vid.renderpath)
5355                 {
5356                 case RENDERPATH_D3D9:
5357 #ifdef SUPPORTD3D
5358                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5359                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5360 #endif
5361                         break;
5362                 case RENDERPATH_D3D10:
5363                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5364                         break;
5365                 case RENDERPATH_D3D11:
5366                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5367                         break;
5368                 case RENDERPATH_GL11:
5369                 case RENDERPATH_GL13:
5370                 case RENDERPATH_GLES1:
5371                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5372                         break;
5373                 case RENDERPATH_SOFT:
5374                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5375                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5376                         break;
5377                 case RENDERPATH_GL20:
5378                 case RENDERPATH_GLES2:
5379                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5380                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5381                         break;
5382                 }
5383         }
5384 }
5385
5386 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5387 {
5388         r_viewport_t viewport;
5389         DrawQ_Finish();
5390
5391         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5392         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);
5393         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5394         R_SetViewport(&viewport);
5395         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5396         GL_Color(1, 1, 1, 1);
5397         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5398         GL_BlendFunc(GL_ONE, GL_ZERO);
5399         GL_ScissorTest(false);
5400         GL_DepthMask(false);
5401         GL_DepthRange(0, 1);
5402         GL_DepthTest(false);
5403         GL_DepthFunc(GL_LEQUAL);
5404         R_EntityMatrix(&identitymatrix);
5405         R_Mesh_ResetTextureState();
5406         GL_PolygonOffset(0, 0);
5407         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5408         switch(vid.renderpath)
5409         {
5410         case RENDERPATH_GL11:
5411         case RENDERPATH_GL13:
5412         case RENDERPATH_GL20:
5413         case RENDERPATH_GLES1:
5414         case RENDERPATH_GLES2:
5415                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5416                 break;
5417         case RENDERPATH_D3D9:
5418         case RENDERPATH_D3D10:
5419         case RENDERPATH_D3D11:
5420         case RENDERPATH_SOFT:
5421                 break;
5422         }
5423         GL_CullFace(GL_NONE);
5424 }
5425
5426 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5427 {
5428         DrawQ_Finish();
5429
5430         R_SetupView(true, fbo, depthtexture, colortexture);
5431         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5432         GL_Color(1, 1, 1, 1);
5433         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5434         GL_BlendFunc(GL_ONE, GL_ZERO);
5435         GL_ScissorTest(true);
5436         GL_DepthMask(true);
5437         GL_DepthRange(0, 1);
5438         GL_DepthTest(true);
5439         GL_DepthFunc(GL_LEQUAL);
5440         R_EntityMatrix(&identitymatrix);
5441         R_Mesh_ResetTextureState();
5442         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5443         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5444         switch(vid.renderpath)
5445         {
5446         case RENDERPATH_GL11:
5447         case RENDERPATH_GL13:
5448         case RENDERPATH_GL20:
5449         case RENDERPATH_GLES1:
5450         case RENDERPATH_GLES2:
5451                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5452                 break;
5453         case RENDERPATH_D3D9:
5454         case RENDERPATH_D3D10:
5455         case RENDERPATH_D3D11:
5456         case RENDERPATH_SOFT:
5457                 break;
5458         }
5459         GL_CullFace(r_refdef.view.cullface_back);
5460 }
5461
5462 /*
5463 ================
5464 R_RenderView_UpdateViewVectors
5465 ================
5466 */
5467 static void R_RenderView_UpdateViewVectors(void)
5468 {
5469         // break apart the view matrix into vectors for various purposes
5470         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5471         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5472         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5473         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5474         // make an inverted copy of the view matrix for tracking sprites
5475         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5476 }
5477
5478 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5479 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5480
5481 static void R_Water_StartFrame(void)
5482 {
5483         int i;
5484         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5485         r_waterstate_waterplane_t *p;
5486         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5487
5488         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5489                 return;
5490
5491         switch(vid.renderpath)
5492         {
5493         case RENDERPATH_GL20:
5494         case RENDERPATH_D3D9:
5495         case RENDERPATH_D3D10:
5496         case RENDERPATH_D3D11:
5497         case RENDERPATH_SOFT:
5498         case RENDERPATH_GLES2:
5499                 break;
5500         case RENDERPATH_GL11:
5501         case RENDERPATH_GL13:
5502         case RENDERPATH_GLES1:
5503                 return;
5504         }
5505
5506         // set waterwidth and waterheight to the water resolution that will be
5507         // used (often less than the screen resolution for faster rendering)
5508         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5509
5510         // calculate desired texture sizes
5511         // can't use water if the card does not support the texture size
5512         if (!r_water.integer || r_showsurfaces.integer)
5513                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5514         else if (vid.support.arb_texture_non_power_of_two)
5515         {
5516                 texturewidth = waterwidth;
5517                 textureheight = waterheight;
5518                 camerawidth = waterwidth;
5519                 cameraheight = waterheight;
5520         }
5521         else
5522         {
5523                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5524                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5525                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5526                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5527         }
5528
5529         // allocate textures as needed
5530         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5531         {
5532                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5533                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5534                 {
5535                         if (p->texture_refraction)
5536                                 R_FreeTexture(p->texture_refraction);
5537                         p->texture_refraction = NULL;
5538                         if (p->fbo_refraction)
5539                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5540                         p->fbo_refraction = 0;
5541                         if (p->texture_reflection)
5542                                 R_FreeTexture(p->texture_reflection);
5543                         p->texture_reflection = NULL;
5544                         if (p->fbo_reflection)
5545                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5546                         p->fbo_reflection = 0;
5547                         if (p->texture_camera)
5548                                 R_FreeTexture(p->texture_camera);
5549                         p->texture_camera = NULL;
5550                         if (p->fbo_camera)
5551                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5552                         p->fbo_camera = 0;
5553                 }
5554                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5555                 r_fb.water.texturewidth = texturewidth;
5556                 r_fb.water.textureheight = textureheight;
5557                 r_fb.water.camerawidth = camerawidth;
5558                 r_fb.water.cameraheight = cameraheight;
5559         }
5560
5561         if (r_fb.water.texturewidth)
5562         {
5563                 int scaledwidth, scaledheight;
5564
5565                 r_fb.water.enabled = true;
5566
5567                 // water resolution is usually reduced
5568                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5569                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5570                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5571
5572                 // set up variables that will be used in shader setup
5573                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5574                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5575                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5576                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5577         }
5578
5579         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5580         r_fb.water.numwaterplanes = 0;
5581 }
5582
5583 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5584 {
5585         int planeindex, bestplaneindex, vertexindex;
5586         vec3_t mins, maxs, normal, center, v, n;
5587         vec_t planescore, bestplanescore;
5588         mplane_t plane;
5589         r_waterstate_waterplane_t *p;
5590         texture_t *t = R_GetCurrentTexture(surface->texture);
5591
5592         rsurface.texture = t;
5593         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5594         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5595         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5596                 return;
5597         // average the vertex normals, find the surface bounds (after deformvertexes)
5598         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5599         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5600         VectorCopy(n, normal);
5601         VectorCopy(v, mins);
5602         VectorCopy(v, maxs);
5603         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5604         {
5605                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5606                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5607                 VectorAdd(normal, n, normal);
5608                 mins[0] = min(mins[0], v[0]);
5609                 mins[1] = min(mins[1], v[1]);
5610                 mins[2] = min(mins[2], v[2]);
5611                 maxs[0] = max(maxs[0], v[0]);
5612                 maxs[1] = max(maxs[1], v[1]);
5613                 maxs[2] = max(maxs[2], v[2]);
5614         }
5615         VectorNormalize(normal);
5616         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5617
5618         VectorCopy(normal, plane.normal);
5619         VectorNormalize(plane.normal);
5620         plane.dist = DotProduct(center, plane.normal);
5621         PlaneClassify(&plane);
5622         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5623         {
5624                 // skip backfaces (except if nocullface is set)
5625 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5626 //                      return;
5627                 VectorNegate(plane.normal, plane.normal);
5628                 plane.dist *= -1;
5629                 PlaneClassify(&plane);
5630         }
5631
5632
5633         // find a matching plane if there is one
5634         bestplaneindex = -1;
5635         bestplanescore = 1048576.0f;
5636         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5637         {
5638                 if(p->camera_entity == t->camera_entity)
5639                 {
5640                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5641                         if (bestplaneindex < 0 || bestplanescore > planescore)
5642                         {
5643                                 bestplaneindex = planeindex;
5644                                 bestplanescore = planescore;
5645                         }
5646                 }
5647         }
5648         planeindex = bestplaneindex;
5649         p = r_fb.water.waterplanes + planeindex;
5650
5651         // if this surface does not fit any known plane rendered this frame, add one
5652         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5653         {
5654                 // store the new plane
5655                 planeindex = r_fb.water.numwaterplanes++;
5656                 p = r_fb.water.waterplanes + planeindex;
5657                 p->plane = plane;
5658                 // clear materialflags and pvs
5659                 p->materialflags = 0;
5660                 p->pvsvalid = false;
5661                 p->camera_entity = t->camera_entity;
5662                 VectorCopy(mins, p->mins);
5663                 VectorCopy(maxs, p->maxs);
5664         }
5665         else
5666         {
5667                 // merge mins/maxs when we're adding this surface to the plane
5668                 p->mins[0] = min(p->mins[0], mins[0]);
5669                 p->mins[1] = min(p->mins[1], mins[1]);
5670                 p->mins[2] = min(p->mins[2], mins[2]);
5671                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5672                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5673                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5674         }
5675         // merge this surface's materialflags into the waterplane
5676         p->materialflags |= t->currentmaterialflags;
5677         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5678         {
5679                 // merge this surface's PVS into the waterplane
5680                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5681                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5682                 {
5683                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5684                         p->pvsvalid = true;
5685                 }
5686         }
5687 }
5688
5689 extern cvar_t r_drawparticles;
5690 extern cvar_t r_drawdecals;
5691
5692 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5693 {
5694         int myscissor[4];
5695         r_refdef_view_t originalview;
5696         r_refdef_view_t myview;
5697         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;
5698         r_waterstate_waterplane_t *p;
5699         vec3_t visorigin;
5700         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5701         char vabuf[1024];
5702
5703         originalview = r_refdef.view;
5704
5705         // lowquality hack, temporarily shut down some cvars and restore afterwards
5706         qualityreduction = r_water_lowquality.integer;
5707         if (qualityreduction > 0)
5708         {
5709                 if (qualityreduction >= 1)
5710                 {
5711                         old_r_shadows = r_shadows.integer;
5712                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5713                         old_r_dlight = r_shadow_realtime_dlight.integer;
5714                         Cvar_SetValueQuick(&r_shadows, 0);
5715                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5716                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5717                 }
5718                 if (qualityreduction >= 2)
5719                 {
5720                         old_r_dynamic = r_dynamic.integer;
5721                         old_r_particles = r_drawparticles.integer;
5722                         old_r_decals = r_drawdecals.integer;
5723                         Cvar_SetValueQuick(&r_dynamic, 0);
5724                         Cvar_SetValueQuick(&r_drawparticles, 0);
5725                         Cvar_SetValueQuick(&r_drawdecals, 0);
5726                 }
5727         }
5728
5729         // make sure enough textures are allocated
5730         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5731         {
5732                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5733                 {
5734                         if (!p->texture_refraction)
5735                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5736                         if (!p->texture_refraction)
5737                                 goto error;
5738                         if (usewaterfbo)
5739                         {
5740                                 if (r_fb.water.depthtexture == NULL)
5741                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5742                                 if (p->fbo_refraction == 0)
5743                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5744                         }
5745                 }
5746                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5747                 {
5748                         if (!p->texture_camera)
5749                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5750                         if (!p->texture_camera)
5751                                 goto error;
5752                         if (usewaterfbo)
5753                         {
5754                                 if (r_fb.water.depthtexture == NULL)
5755                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5756                                 if (p->fbo_camera == 0)
5757                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5758                         }
5759                 }
5760
5761                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5762                 {
5763                         if (!p->texture_reflection)
5764                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5765                         if (!p->texture_reflection)
5766                                 goto error;
5767                         if (usewaterfbo)
5768                         {
5769                                 if (r_fb.water.depthtexture == NULL)
5770                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5771                                 if (p->fbo_reflection == 0)
5772                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5773                         }
5774                 }
5775         }
5776
5777         // render views
5778         r_refdef.view = originalview;
5779         r_refdef.view.showdebug = false;
5780         r_refdef.view.width = r_fb.water.waterwidth;
5781         r_refdef.view.height = r_fb.water.waterheight;
5782         r_refdef.view.useclipplane = true;
5783         myview = r_refdef.view;
5784         r_fb.water.renderingscene = true;
5785         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5786         {
5787                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5788                 {
5789                         r_refdef.view = myview;
5790                         if(r_water_scissormode.integer)
5791                         {
5792                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5793                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5794                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5795                         }
5796
5797                         // render reflected scene and copy into texture
5798                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5799                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5800                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5801                         r_refdef.view.clipplane = p->plane;
5802                         // reverse the cullface settings for this render
5803                         r_refdef.view.cullface_front = GL_FRONT;
5804                         r_refdef.view.cullface_back = GL_BACK;
5805                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5806                         {
5807                                 r_refdef.view.usecustompvs = true;
5808                                 if (p->pvsvalid)
5809                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5810                                 else
5811                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5812                         }
5813
5814                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5815                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5816                         R_ClearScreen(r_refdef.fogenabled);
5817                         if(r_water_scissormode.integer & 2)
5818                                 R_View_UpdateWithScissor(myscissor);
5819                         else
5820                                 R_View_Update();
5821                         if(r_water_scissormode.integer & 1)
5822                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5823                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5824
5825                         if (!p->fbo_reflection)
5826                                 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);
5827                         r_fb.water.hideplayer = false;
5828                 }
5829
5830                 // render the normal view scene and copy into texture
5831                 // (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)
5832                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5833                 {
5834                         r_refdef.view = myview;
5835                         if(r_water_scissormode.integer)
5836                         {
5837                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5838                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5839                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5840                         }
5841
5842                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5843
5844                         r_refdef.view.clipplane = p->plane;
5845                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5846                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5847
5848                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5849                         {
5850                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5851                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5852                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5853                                 R_RenderView_UpdateViewVectors();
5854                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5855                                 {
5856                                         r_refdef.view.usecustompvs = true;
5857                                         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);
5858                                 }
5859                         }
5860
5861                         PlaneClassify(&r_refdef.view.clipplane);
5862
5863                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5864                         R_ClearScreen(r_refdef.fogenabled);
5865                         if(r_water_scissormode.integer & 2)
5866                                 R_View_UpdateWithScissor(myscissor);
5867                         else
5868                                 R_View_Update();
5869                         if(r_water_scissormode.integer & 1)
5870                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5871                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5872
5873                         if (!p->fbo_refraction)
5874                                 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);
5875                         r_fb.water.hideplayer = false;
5876                 }
5877                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5878                 {
5879                         r_refdef.view = myview;
5880
5881                         r_refdef.view.clipplane = p->plane;
5882                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5883                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5884
5885                         r_refdef.view.width = r_fb.water.camerawidth;
5886                         r_refdef.view.height = r_fb.water.cameraheight;
5887                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5888                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5889                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5890                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5891
5892                         if(p->camera_entity)
5893                         {
5894                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5895                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5896                         }
5897
5898                         // note: all of the view is used for displaying... so
5899                         // there is no use in scissoring
5900
5901                         // reverse the cullface settings for this render
5902                         r_refdef.view.cullface_front = GL_FRONT;
5903                         r_refdef.view.cullface_back = GL_BACK;
5904                         // also reverse the view matrix
5905                         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
5906                         R_RenderView_UpdateViewVectors();
5907                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5908                         {
5909                                 r_refdef.view.usecustompvs = true;
5910                                 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);
5911                         }
5912                         
5913                         // camera needs no clipplane
5914                         r_refdef.view.useclipplane = false;
5915
5916                         PlaneClassify(&r_refdef.view.clipplane);
5917
5918                         r_fb.water.hideplayer = false;
5919
5920                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5921                         R_ClearScreen(r_refdef.fogenabled);
5922                         R_View_Update();
5923                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5924
5925                         if (!p->fbo_camera)
5926                                 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);
5927                         r_fb.water.hideplayer = false;
5928                 }
5929
5930         }
5931         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5932         r_fb.water.renderingscene = false;
5933         r_refdef.view = originalview;
5934         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5935         if (!r_fb.water.depthtexture)
5936                 R_ClearScreen(r_refdef.fogenabled);
5937         R_View_Update();
5938         goto finish;
5939 error:
5940         r_refdef.view = originalview;
5941         r_fb.water.renderingscene = false;
5942         Cvar_SetValueQuick(&r_water, 0);
5943         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5944 finish:
5945         // lowquality hack, restore cvars
5946         if (qualityreduction > 0)
5947         {
5948                 if (qualityreduction >= 1)
5949                 {
5950                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5951                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5952                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5953                 }
5954                 if (qualityreduction >= 2)
5955                 {
5956                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5957                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5958                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5959                 }
5960         }
5961 }
5962
5963 static void R_Bloom_StartFrame(void)
5964 {
5965         int i;
5966         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5967         int viewwidth, viewheight;
5968         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5969         textype_t textype = TEXTYPE_COLORBUFFER;
5970
5971         switch (vid.renderpath)
5972         {
5973         case RENDERPATH_GL20:
5974         case RENDERPATH_GLES2:
5975                 if (vid.support.ext_framebuffer_object)
5976                 {
5977                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5978                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5979                 }
5980                 break;
5981         case RENDERPATH_GL11:
5982         case RENDERPATH_GL13:
5983         case RENDERPATH_GLES1:
5984         case RENDERPATH_D3D9:
5985         case RENDERPATH_D3D10:
5986         case RENDERPATH_D3D11:
5987         case RENDERPATH_SOFT:
5988                 break;
5989         }
5990
5991         if (r_viewscale_fpsscaling.integer)
5992         {
5993                 double actualframetime;
5994                 double targetframetime;
5995                 double adjust;
5996                 actualframetime = r_refdef.lastdrawscreentime;
5997                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5998                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5999                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6000                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6001                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6002                 viewscalefpsadjusted += adjust;
6003                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6004         }
6005         else
6006                 viewscalefpsadjusted = 1.0f;
6007
6008         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6009
6010         switch(vid.renderpath)
6011         {
6012         case RENDERPATH_GL20:
6013         case RENDERPATH_D3D9:
6014         case RENDERPATH_D3D10:
6015         case RENDERPATH_D3D11:
6016         case RENDERPATH_SOFT:
6017         case RENDERPATH_GLES2:
6018                 break;
6019         case RENDERPATH_GL11:
6020         case RENDERPATH_GL13:
6021         case RENDERPATH_GLES1:
6022                 return;
6023         }
6024
6025         // set bloomwidth and bloomheight to the bloom resolution that will be
6026         // used (often less than the screen resolution for faster rendering)
6027         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6028         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6029         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6030         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6031         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6032
6033         // calculate desired texture sizes
6034         if (vid.support.arb_texture_non_power_of_two)
6035         {
6036                 screentexturewidth = vid.width;
6037                 screentextureheight = vid.height;
6038                 bloomtexturewidth = r_fb.bloomwidth;
6039                 bloomtextureheight = r_fb.bloomheight;
6040         }
6041         else
6042         {
6043                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6044                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6045                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6046                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6047         }
6048
6049         if ((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))
6050         {
6051                 Cvar_SetValueQuick(&r_bloom, 0);
6052                 Cvar_SetValueQuick(&r_motionblur, 0);
6053                 Cvar_SetValueQuick(&r_damageblur, 0);
6054         }
6055
6056         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6057          && !r_bloom.integer
6058          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6059          && !useviewfbo
6060          && r_viewscale.value == 1.0f
6061          && !r_viewscale_fpsscaling.integer)
6062                 screentexturewidth = screentextureheight = 0;
6063         if (!r_bloom.integer)
6064                 bloomtexturewidth = bloomtextureheight = 0;
6065
6066         // allocate textures as needed
6067         if (r_fb.screentexturewidth != screentexturewidth
6068          || r_fb.screentextureheight != screentextureheight
6069          || r_fb.bloomtexturewidth != bloomtexturewidth
6070          || r_fb.bloomtextureheight != bloomtextureheight
6071          || r_fb.textype != textype
6072          || useviewfbo != (r_fb.fbo != 0))
6073         {
6074                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6075                 {
6076                         if (r_fb.bloomtexture[i])
6077                                 R_FreeTexture(r_fb.bloomtexture[i]);
6078                         r_fb.bloomtexture[i] = NULL;
6079
6080                         if (r_fb.bloomfbo[i])
6081                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6082                         r_fb.bloomfbo[i] = 0;
6083                 }
6084
6085                 if (r_fb.fbo)
6086                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6087                 r_fb.fbo = 0;
6088
6089                 if (r_fb.colortexture)
6090                         R_FreeTexture(r_fb.colortexture);
6091                 r_fb.colortexture = NULL;
6092
6093                 if (r_fb.depthtexture)
6094                         R_FreeTexture(r_fb.depthtexture);
6095                 r_fb.depthtexture = NULL;
6096
6097                 if (r_fb.ghosttexture)
6098                         R_FreeTexture(r_fb.ghosttexture);
6099                 r_fb.ghosttexture = NULL;
6100
6101                 r_fb.screentexturewidth = screentexturewidth;
6102                 r_fb.screentextureheight = screentextureheight;
6103                 r_fb.bloomtexturewidth = bloomtexturewidth;
6104                 r_fb.bloomtextureheight = bloomtextureheight;
6105                 r_fb.textype = textype;
6106
6107                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6108                 {
6109                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6110                                 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6111                         r_fb.ghosttexture_valid = false;
6112                         r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6113                         if (useviewfbo)
6114                         {
6115                                 // FIXME: choose depth bits based on a cvar
6116                                 r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false);
6117                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6118                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6119 #ifndef USE_GLES2
6120                                 // render depth into one texture and color into the other
6121                                 if (qglDrawBuffer)
6122                                 {
6123                                         int status;
6124                                         qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6125                                         qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6126                                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6127                                         if (status != GL_FRAMEBUFFER_COMPLETE)
6128                                                 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6129                                 }
6130 #endif
6131                         }
6132                 }
6133
6134                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6135                 {
6136                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6137                         {
6138                                 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6139                                 if (useviewfbo)
6140                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6141                         }
6142                 }
6143         }
6144
6145         // bloom texture is a different resolution
6146         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6147         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6148         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6149         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6150         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6151
6152         // set up a texcoord array for the full resolution screen image
6153         // (we have to keep this around to copy back during final render)
6154         r_fb.screentexcoord2f[0] = 0;
6155         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6156         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6157         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6158         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6159         r_fb.screentexcoord2f[5] = 0;
6160         r_fb.screentexcoord2f[6] = 0;
6161         r_fb.screentexcoord2f[7] = 0;
6162
6163         // set up a texcoord array for the reduced resolution bloom image
6164         // (which will be additive blended over the screen image)
6165         r_fb.bloomtexcoord2f[0] = 0;
6166         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6167         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6168         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6169         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6170         r_fb.bloomtexcoord2f[5] = 0;
6171         r_fb.bloomtexcoord2f[6] = 0;
6172         r_fb.bloomtexcoord2f[7] = 0;
6173
6174         switch(vid.renderpath)
6175         {
6176         case RENDERPATH_GL11:
6177         case RENDERPATH_GL13:
6178         case RENDERPATH_GL20:
6179         case RENDERPATH_SOFT:
6180         case RENDERPATH_GLES1:
6181         case RENDERPATH_GLES2:
6182                 break;
6183         case RENDERPATH_D3D9:
6184         case RENDERPATH_D3D10:
6185         case RENDERPATH_D3D11:
6186                 {
6187                         int i;
6188                         for (i = 0;i < 4;i++)
6189                         {
6190                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6191                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6192                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6193                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6194                         }
6195                 }
6196                 break;
6197         }
6198
6199         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6200
6201         if (r_fb.fbo)
6202                 r_refdef.view.clear = true;
6203 }
6204
6205 static void R_Bloom_MakeTexture(void)
6206 {
6207         int x, range, dir;
6208         float xoffset, yoffset, r, brighten;
6209         rtexture_t *intex;
6210         float colorscale = r_bloom_colorscale.value;
6211
6212         r_refdef.stats.bloom++;
6213
6214         if (!r_fb.fbo)
6215         {
6216                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6217                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6218         }
6219
6220         // scale down screen texture to the bloom texture size
6221         CHECKGLERROR
6222         r_fb.bloomindex = 0;
6223         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6224         R_SetViewport(&r_fb.bloomviewport);
6225         GL_BlendFunc(GL_ONE, GL_ZERO);
6226         GL_Color(colorscale, colorscale, colorscale, 1);
6227         // 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...
6228         switch(vid.renderpath)
6229         {
6230         case RENDERPATH_GL11:
6231         case RENDERPATH_GL13:
6232         case RENDERPATH_GL20:
6233         case RENDERPATH_GLES1:
6234         case RENDERPATH_GLES2:
6235         case RENDERPATH_SOFT:
6236                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6237                 break;
6238         case RENDERPATH_D3D9:
6239         case RENDERPATH_D3D10:
6240         case RENDERPATH_D3D11:
6241                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6242                 break;
6243         }
6244         // TODO: do boxfilter scale-down in shader?
6245         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6246         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6247         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6248
6249         // we now have a properly scaled bloom image
6250         if (!r_fb.bloomfbo[r_fb.bloomindex])
6251         {
6252                 // copy it into the bloom texture
6253                 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6254                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6255         }
6256
6257         // multiply bloom image by itself as many times as desired
6258         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6259         {
6260                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6261                 r_fb.bloomindex ^= 1;
6262                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6263                 x *= 2;
6264                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6265                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6266                 GL_Color(r,r,r,1);
6267                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6268                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6269                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6270                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6271
6272                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6273                 {
6274                         // copy the darkened image to a texture
6275                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6276                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6277                 }
6278         }
6279
6280         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6281         brighten = r_bloom_brighten.value;
6282         brighten = sqrt(brighten);
6283         if(range >= 1)
6284                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6285
6286         for (dir = 0;dir < 2;dir++)
6287         {
6288                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6289                 r_fb.bloomindex ^= 1;
6290                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6291                 // blend on at multiple vertical offsets to achieve a vertical blur
6292                 // TODO: do offset blends using GLSL
6293                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6294                 GL_BlendFunc(GL_ONE, GL_ZERO);
6295                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6296                 for (x = -range;x <= range;x++)
6297                 {
6298                         if (!dir){xoffset = 0;yoffset = x;}
6299                         else {xoffset = x;yoffset = 0;}
6300                         xoffset /= (float)r_fb.bloomtexturewidth;
6301                         yoffset /= (float)r_fb.bloomtextureheight;
6302                         // compute a texcoord array with the specified x and y offset
6303                         r_fb.offsettexcoord2f[0] = xoffset+0;
6304                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6305                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6306                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6307                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6308                         r_fb.offsettexcoord2f[5] = yoffset+0;
6309                         r_fb.offsettexcoord2f[6] = xoffset+0;
6310                         r_fb.offsettexcoord2f[7] = yoffset+0;
6311                         // this r value looks like a 'dot' particle, fading sharply to
6312                         // black at the edges
6313                         // (probably not realistic but looks good enough)
6314                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6315                         //r = brighten/(range*2+1);
6316                         r = brighten / (range * 2 + 1);
6317                         if(range >= 1)
6318                                 r *= (1 - x*x/(float)(range*range));
6319                         GL_Color(r, r, r, 1);
6320                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6321                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6322                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6323                         GL_BlendFunc(GL_ONE, GL_ONE);
6324                 }
6325
6326                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6327                 {
6328                         // copy the vertically or horizontally blurred bloom view to a texture
6329                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6330                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6331                 }
6332         }
6333 }
6334
6335 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6336 {
6337         unsigned int permutation;
6338         float uservecs[4][4];
6339
6340         switch (vid.renderpath)
6341         {
6342         case RENDERPATH_GL20:
6343         case RENDERPATH_D3D9:
6344         case RENDERPATH_D3D10:
6345         case RENDERPATH_D3D11:
6346         case RENDERPATH_SOFT:
6347         case RENDERPATH_GLES2:
6348                 permutation =
6349                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6350                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6351                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6352                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6353                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6354
6355                 if (r_fb.colortexture)
6356                 {
6357                         if (!r_fb.fbo)
6358                         {
6359                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6360                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6361                         }
6362
6363                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6364                         {
6365                                 // declare variables
6366                                 float blur_factor, blur_mouseaccel, blur_velocity;
6367                                 static float blur_average; 
6368                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6369
6370                                 // set a goal for the factoring
6371                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6372                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6373                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6374                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6375                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6376                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6377
6378                                 // from the goal, pick an averaged value between goal and last value
6379                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6380                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6381
6382                                 // enforce minimum amount of blur 
6383                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6384
6385                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6386
6387                                 // calculate values into a standard alpha
6388                                 cl.motionbluralpha = 1 - exp(-
6389                                                 (
6390                                                  (r_motionblur.value * blur_factor / 80)
6391                                                  +
6392                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6393                                                 )
6394                                                 /
6395                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6396                                           );
6397
6398                                 // randomization for the blur value to combat persistent ghosting
6399                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6400                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6401
6402                                 // apply the blur
6403                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6404                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6405                                 {
6406                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6407                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6408                                         switch(vid.renderpath)
6409                                         {
6410                                         case RENDERPATH_GL11:
6411                                         case RENDERPATH_GL13:
6412                                         case RENDERPATH_GL20:
6413                                         case RENDERPATH_GLES1:
6414                                         case RENDERPATH_GLES2:
6415                                         case RENDERPATH_SOFT:
6416                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6417                                                 break;
6418                                         case RENDERPATH_D3D9:
6419                                         case RENDERPATH_D3D10:
6420                                         case RENDERPATH_D3D11:
6421                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6422                                                 break;
6423                                         }
6424                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6425                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6426                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6427                                 }
6428
6429                                 // updates old view angles for next pass
6430                                 VectorCopy(cl.viewangles, blur_oldangles);
6431
6432                                 // copy view into the ghost texture
6433                                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6434                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6435                                 r_fb.ghosttexture_valid = true;
6436                         }
6437                 }
6438                 else
6439                 {
6440                         // no r_fb.colortexture means we're rendering to the real fb
6441                         // we may still have to do view tint...
6442                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6443                         {
6444                                 // apply a color tint to the whole view
6445                                 R_ResetViewRendering2D(0, NULL, NULL);
6446                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6447                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6448                                 R_SetupShader_Generic_NoTexture(false, true);
6449                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6450                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6451                         }
6452                         break; // no screen processing, no bloom, skip it
6453                 }
6454
6455                 if (r_fb.bloomtexture[0])
6456                 {
6457                         // make the bloom texture
6458                         R_Bloom_MakeTexture();
6459                 }
6460
6461 #if _MSC_VER >= 1400
6462 #define sscanf sscanf_s
6463 #endif
6464                 memset(uservecs, 0, sizeof(uservecs));
6465                 if (r_glsl_postprocess_uservec1_enable.integer)
6466                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6467                 if (r_glsl_postprocess_uservec2_enable.integer)
6468                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6469                 if (r_glsl_postprocess_uservec3_enable.integer)
6470                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6471                 if (r_glsl_postprocess_uservec4_enable.integer)
6472                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6473
6474                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6475                 GL_Color(1, 1, 1, 1);
6476                 GL_BlendFunc(GL_ONE, GL_ZERO);
6477
6478                 switch(vid.renderpath)
6479                 {
6480                 case RENDERPATH_GL20:
6481                 case RENDERPATH_GLES2:
6482                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6483                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6484                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6485                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6486                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6487                         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]);
6488                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6489                         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]);
6490                         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]);
6491                         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]);
6492                         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]);
6493                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6494                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6495                         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);
6496                         break;
6497                 case RENDERPATH_D3D9:
6498 #ifdef SUPPORTD3D
6499                         // 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...
6500                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6501                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6502                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6503                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6504                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6505                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6506                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6507                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6508                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6509                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6510                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6511                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6512                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6513                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6514 #endif
6515                         break;
6516                 case RENDERPATH_D3D10:
6517                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6518                         break;
6519                 case RENDERPATH_D3D11:
6520                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6521                         break;
6522                 case RENDERPATH_SOFT:
6523                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6524                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6525                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6526                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6527                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6528                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6529                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6530                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6531                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6532                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6533                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6534                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6535                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6536                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6537                         break;
6538                 default:
6539                         break;
6540                 }
6541                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6542                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6543                 break;
6544         case RENDERPATH_GL11:
6545         case RENDERPATH_GL13:
6546         case RENDERPATH_GLES1:
6547                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6548                 {
6549                         // apply a color tint to the whole view
6550                         R_ResetViewRendering2D(0, NULL, NULL);
6551                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6552                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6553                         R_SetupShader_Generic_NoTexture(false, true);
6554                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6555                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6556                 }
6557                 break;
6558         }
6559 }
6560
6561 matrix4x4_t r_waterscrollmatrix;
6562
6563 void R_UpdateFog(void)
6564 {
6565         // Nehahra fog
6566         if (gamemode == GAME_NEHAHRA)
6567         {
6568                 if (gl_fogenable.integer)
6569                 {
6570                         r_refdef.oldgl_fogenable = true;
6571                         r_refdef.fog_density = gl_fogdensity.value;
6572                         r_refdef.fog_red = gl_fogred.value;
6573                         r_refdef.fog_green = gl_foggreen.value;
6574                         r_refdef.fog_blue = gl_fogblue.value;
6575                         r_refdef.fog_alpha = 1;
6576                         r_refdef.fog_start = 0;
6577                         r_refdef.fog_end = gl_skyclip.value;
6578                         r_refdef.fog_height = 1<<30;
6579                         r_refdef.fog_fadedepth = 128;
6580                 }
6581                 else if (r_refdef.oldgl_fogenable)
6582                 {
6583                         r_refdef.oldgl_fogenable = false;
6584                         r_refdef.fog_density = 0;
6585                         r_refdef.fog_red = 0;
6586                         r_refdef.fog_green = 0;
6587                         r_refdef.fog_blue = 0;
6588                         r_refdef.fog_alpha = 0;
6589                         r_refdef.fog_start = 0;
6590                         r_refdef.fog_end = 0;
6591                         r_refdef.fog_height = 1<<30;
6592                         r_refdef.fog_fadedepth = 128;
6593                 }
6594         }
6595
6596         // fog parms
6597         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6598         r_refdef.fog_start = max(0, r_refdef.fog_start);
6599         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6600
6601         if (r_refdef.fog_density && r_drawfog.integer)
6602         {
6603                 r_refdef.fogenabled = true;
6604                 // this is the point where the fog reaches 0.9986 alpha, which we
6605                 // consider a good enough cutoff point for the texture
6606                 // (0.9986 * 256 == 255.6)
6607                 if (r_fog_exp2.integer)
6608                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6609                 else
6610                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6611                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6612                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6613                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6614                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6615                         R_BuildFogHeightTexture();
6616                 // fog color was already set
6617                 // update the fog texture
6618                 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)
6619                         R_BuildFogTexture();
6620                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6621                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6622         }
6623         else
6624                 r_refdef.fogenabled = false;
6625
6626         // fog color
6627         if (r_refdef.fog_density)
6628         {
6629                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6630                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6631                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6632
6633                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6634                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6635                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6636                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6637
6638                 {
6639                         vec3_t fogvec;
6640                         VectorCopy(r_refdef.fogcolor, fogvec);
6641                         //   color.rgb *= ContrastBoost * SceneBrightness;
6642                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6643                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6644                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6645                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6646                 }
6647         }
6648 }
6649
6650 void R_UpdateVariables(void)
6651 {
6652         R_Textures_Frame();
6653
6654         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6655
6656         r_refdef.farclip = r_farclip_base.value;
6657         if (r_refdef.scene.worldmodel)
6658                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6659         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6660
6661         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6662                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6663         r_refdef.polygonfactor = 0;
6664         r_refdef.polygonoffset = 0;
6665         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6666         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6667
6668         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6669         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6670         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6671         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6672         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6673         if (FAKELIGHT_ENABLED)
6674         {
6675                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6676         }
6677         if (r_showsurfaces.integer)
6678         {
6679                 r_refdef.scene.rtworld = false;
6680                 r_refdef.scene.rtworldshadows = false;
6681                 r_refdef.scene.rtdlight = false;
6682                 r_refdef.scene.rtdlightshadows = false;
6683                 r_refdef.lightmapintensity = 0;
6684         }
6685
6686         switch(vid.renderpath)
6687         {
6688         case RENDERPATH_GL20:
6689         case RENDERPATH_D3D9:
6690         case RENDERPATH_D3D10:
6691         case RENDERPATH_D3D11:
6692         case RENDERPATH_SOFT:
6693         case RENDERPATH_GLES2:
6694                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6695                 {
6696                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6697                         {
6698                                 // build GLSL gamma texture
6699 #define RAMPWIDTH 256
6700                                 unsigned short ramp[RAMPWIDTH * 3];
6701                                 unsigned char rampbgr[RAMPWIDTH][4];
6702                                 int i;
6703
6704                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6705
6706                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6707                                 for(i = 0; i < RAMPWIDTH; ++i)
6708                                 {
6709                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6710                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6711                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6712                                         rampbgr[i][3] = 0;
6713                                 }
6714                                 if (r_texture_gammaramps)
6715                                 {
6716                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6717                                 }
6718                                 else
6719                                 {
6720                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6721                                 }
6722                         }
6723                 }
6724                 else
6725                 {
6726                         // remove GLSL gamma texture
6727                 }
6728                 break;
6729         case RENDERPATH_GL11:
6730         case RENDERPATH_GL13:
6731         case RENDERPATH_GLES1:
6732                 break;
6733         }
6734 }
6735
6736 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6737 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6738 /*
6739 ================
6740 R_SelectScene
6741 ================
6742 */
6743 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6744         if( scenetype != r_currentscenetype ) {
6745                 // store the old scenetype
6746                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6747                 r_currentscenetype = scenetype;
6748                 // move in the new scene
6749                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6750         }
6751 }
6752
6753 /*
6754 ================
6755 R_GetScenePointer
6756 ================
6757 */
6758 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6759 {
6760         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6761         if( scenetype == r_currentscenetype ) {
6762                 return &r_refdef.scene;
6763         } else {
6764                 return &r_scenes_store[ scenetype ];
6765         }
6766 }
6767
6768 static int R_SortEntities_Compare(const void *ap, const void *bp)
6769 {
6770         const entity_render_t *a = *(const entity_render_t **)ap;
6771         const entity_render_t *b = *(const entity_render_t **)bp;
6772
6773         // 1. compare model
6774         if(a->model < b->model)
6775                 return -1;
6776         if(a->model > b->model)
6777                 return +1;
6778
6779         // 2. compare skin
6780         // TODO possibly calculate the REAL skinnum here first using
6781         // skinscenes?
6782         if(a->skinnum < b->skinnum)
6783                 return -1;
6784         if(a->skinnum > b->skinnum)
6785                 return +1;
6786
6787         // everything we compared is equal
6788         return 0;
6789 }
6790 static void R_SortEntities(void)
6791 {
6792         // below or equal 2 ents, sorting never gains anything
6793         if(r_refdef.scene.numentities <= 2)
6794                 return;
6795         // sort
6796         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6797 }
6798
6799 /*
6800 ================
6801 R_RenderView
6802 ================
6803 */
6804 int dpsoftrast_test;
6805 extern cvar_t r_shadow_bouncegrid;
6806 void R_RenderView(void)
6807 {
6808         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6809         int fbo;
6810         rtexture_t *depthtexture;
6811         rtexture_t *colortexture;
6812
6813         dpsoftrast_test = r_test.integer;
6814
6815         if (r_timereport_active)
6816                 R_TimeReport("start");
6817         r_textureframe++; // used only by R_GetCurrentTexture
6818         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6819
6820         if(R_CompileShader_CheckStaticParms())
6821                 R_GLSL_Restart_f();
6822
6823         if (!r_drawentities.integer)
6824                 r_refdef.scene.numentities = 0;
6825         else if (r_sortentities.integer)
6826                 R_SortEntities();
6827
6828         R_AnimCache_ClearCache();
6829         R_FrameData_NewFrame();
6830
6831         /* adjust for stereo display */
6832         if(R_Stereo_Active())
6833         {
6834                 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);
6835                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6836         }
6837
6838         if (r_refdef.view.isoverlay)
6839         {
6840                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6841                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6842                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6843                 R_TimeReport("depthclear");
6844
6845                 r_refdef.view.showdebug = false;
6846
6847                 r_fb.water.enabled = false;
6848                 r_fb.water.numwaterplanes = 0;
6849
6850                 R_RenderScene(0, NULL, NULL);
6851
6852                 r_refdef.view.matrix = originalmatrix;
6853
6854                 CHECKGLERROR
6855                 return;
6856         }
6857
6858         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6859         {
6860                 r_refdef.view.matrix = originalmatrix;
6861                 return;
6862         }
6863
6864         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6865
6866         R_RenderView_UpdateViewVectors();
6867
6868         R_Shadow_UpdateWorldLightSelection();
6869
6870         R_Bloom_StartFrame();
6871         R_Water_StartFrame();
6872
6873         // now we probably have an fbo to render into
6874         fbo = r_fb.fbo;
6875         depthtexture = r_fb.depthtexture;
6876         colortexture = r_fb.colortexture;
6877
6878         CHECKGLERROR
6879         if (r_timereport_active)
6880                 R_TimeReport("viewsetup");
6881
6882         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6883
6884         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6885         {
6886                 R_ClearScreen(r_refdef.fogenabled);
6887                 if (r_timereport_active)
6888                         R_TimeReport("viewclear");
6889         }
6890         r_refdef.view.clear = true;
6891
6892         r_refdef.view.showdebug = true;
6893
6894         R_View_Update();
6895         if (r_timereport_active)
6896                 R_TimeReport("visibility");
6897
6898         R_Shadow_UpdateBounceGridTexture();
6899         if (r_timereport_active && r_shadow_bouncegrid.integer)
6900                 R_TimeReport("bouncegrid");
6901
6902         r_fb.water.numwaterplanes = 0;
6903         if (r_fb.water.enabled)
6904                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6905
6906         R_RenderScene(fbo, depthtexture, colortexture);
6907         r_fb.water.numwaterplanes = 0;
6908
6909         R_BlendView(fbo, depthtexture, colortexture);
6910         if (r_timereport_active)
6911                 R_TimeReport("blendview");
6912
6913         GL_Scissor(0, 0, vid.width, vid.height);
6914         GL_ScissorTest(false);
6915
6916         r_refdef.view.matrix = originalmatrix;
6917
6918         CHECKGLERROR
6919 }
6920
6921 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6922 {
6923         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6924         {
6925                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6926                 if (r_timereport_active)
6927                         R_TimeReport("waterworld");
6928         }
6929
6930         // don't let sound skip if going slow
6931         if (r_refdef.scene.extraupdate)
6932                 S_ExtraUpdate ();
6933
6934         R_DrawModelsAddWaterPlanes();
6935         if (r_timereport_active)
6936                 R_TimeReport("watermodels");
6937
6938         if (r_fb.water.numwaterplanes)
6939         {
6940                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6941                 if (r_timereport_active)
6942                         R_TimeReport("waterscenes");
6943         }
6944 }
6945
6946 extern cvar_t cl_locs_show;
6947 static void R_DrawLocs(void);
6948 static void R_DrawEntityBBoxes(void);
6949 static void R_DrawModelDecals(void);
6950 extern cvar_t cl_decals_newsystem;
6951 extern qboolean r_shadow_usingdeferredprepass;
6952 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6953 {
6954         qboolean shadowmapping = false;
6955
6956         if (r_timereport_active)
6957                 R_TimeReport("beginscene");
6958
6959         r_refdef.stats.renders++;
6960
6961         R_UpdateFog();
6962
6963         // don't let sound skip if going slow
6964         if (r_refdef.scene.extraupdate)
6965                 S_ExtraUpdate ();
6966
6967         R_MeshQueue_BeginScene();
6968
6969         R_SkyStartFrame();
6970
6971         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);
6972
6973         if (r_timereport_active)
6974                 R_TimeReport("skystartframe");
6975
6976         if (cl.csqc_vidvars.drawworld)
6977         {
6978                 // don't let sound skip if going slow
6979                 if (r_refdef.scene.extraupdate)
6980                         S_ExtraUpdate ();
6981
6982                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6983                 {
6984                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6985                         if (r_timereport_active)
6986                                 R_TimeReport("worldsky");
6987                 }
6988
6989                 if (R_DrawBrushModelsSky() && r_timereport_active)
6990                         R_TimeReport("bmodelsky");
6991
6992                 if (skyrendermasked && skyrenderlater)
6993                 {
6994                         // we have to force off the water clipping plane while rendering sky
6995                         R_SetupView(false, fbo, depthtexture, colortexture);
6996                         R_Sky();
6997                         R_SetupView(true, fbo, depthtexture, colortexture);
6998                         if (r_timereport_active)
6999                                 R_TimeReport("sky");
7000                 }
7001         }
7002
7003         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7004         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7005                 R_Shadow_PrepareModelShadows();
7006         if (r_timereport_active)
7007                 R_TimeReport("preparelights");
7008
7009         if (R_Shadow_ShadowMappingEnabled())
7010                 shadowmapping = true;
7011
7012         if (r_shadow_usingdeferredprepass)
7013                 R_Shadow_DrawPrepass();
7014
7015         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7016         {
7017                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7018                 if (r_timereport_active)
7019                         R_TimeReport("worlddepth");
7020         }
7021         if (r_depthfirst.integer >= 2)
7022         {
7023                 R_DrawModelsDepth();
7024                 if (r_timereport_active)
7025                         R_TimeReport("modeldepth");
7026         }
7027
7028         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7029         {
7030                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7031                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7032                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7033                 // don't let sound skip if going slow
7034                 if (r_refdef.scene.extraupdate)
7035                         S_ExtraUpdate ();
7036         }
7037
7038         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7039         {
7040                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7041                 if (r_timereport_active)
7042                         R_TimeReport("world");
7043         }
7044
7045         // don't let sound skip if going slow
7046         if (r_refdef.scene.extraupdate)
7047                 S_ExtraUpdate ();
7048
7049         R_DrawModels();
7050         if (r_timereport_active)
7051                 R_TimeReport("models");
7052
7053         // don't let sound skip if going slow
7054         if (r_refdef.scene.extraupdate)
7055                 S_ExtraUpdate ();
7056
7057         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7058         {
7059                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7060                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7061                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7062                 // don't let sound skip if going slow
7063                 if (r_refdef.scene.extraupdate)
7064                         S_ExtraUpdate ();
7065         }
7066
7067         if (!r_shadow_usingdeferredprepass)
7068         {
7069                 R_Shadow_DrawLights();
7070                 if (r_timereport_active)
7071                         R_TimeReport("rtlights");
7072         }
7073
7074         // don't let sound skip if going slow
7075         if (r_refdef.scene.extraupdate)
7076                 S_ExtraUpdate ();
7077
7078         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7079         {
7080                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7081                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7082                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7083                 // don't let sound skip if going slow
7084                 if (r_refdef.scene.extraupdate)
7085                         S_ExtraUpdate ();
7086         }
7087
7088         if (cl.csqc_vidvars.drawworld)
7089         {
7090                 if (cl_decals_newsystem.integer)
7091                 {
7092                         R_DrawModelDecals();
7093                         if (r_timereport_active)
7094                                 R_TimeReport("modeldecals");
7095                 }
7096                 else
7097                 {
7098                         R_DrawDecals();
7099                         if (r_timereport_active)
7100                                 R_TimeReport("decals");
7101                 }
7102
7103                 R_DrawParticles();
7104                 if (r_timereport_active)
7105                         R_TimeReport("particles");
7106
7107                 R_DrawExplosions();
7108                 if (r_timereport_active)
7109                         R_TimeReport("explosions");
7110
7111                 R_DrawLightningBeams();
7112                 if (r_timereport_active)
7113                         R_TimeReport("lightning");
7114         }
7115
7116         if (cl.csqc_loaded)
7117                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7118
7119         if (r_refdef.view.showdebug)
7120         {
7121                 if (cl_locs_show.integer)
7122                 {
7123                         R_DrawLocs();
7124                         if (r_timereport_active)
7125                                 R_TimeReport("showlocs");
7126                 }
7127
7128                 if (r_drawportals.integer)
7129                 {
7130                         R_DrawPortals();
7131                         if (r_timereport_active)
7132                                 R_TimeReport("portals");
7133                 }
7134
7135                 if (r_showbboxes.value > 0)
7136                 {
7137                         R_DrawEntityBBoxes();
7138                         if (r_timereport_active)
7139                                 R_TimeReport("bboxes");
7140                 }
7141         }
7142
7143         if (r_transparent.integer)
7144         {
7145                 R_MeshQueue_RenderTransparent();
7146                 if (r_timereport_active)
7147                         R_TimeReport("drawtrans");
7148         }
7149
7150         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))
7151         {
7152                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7153                 if (r_timereport_active)
7154                         R_TimeReport("worlddebug");
7155                 R_DrawModelsDebug();
7156                 if (r_timereport_active)
7157                         R_TimeReport("modeldebug");
7158         }
7159
7160         if (cl.csqc_vidvars.drawworld)
7161         {
7162                 R_Shadow_DrawCoronas();
7163                 if (r_timereport_active)
7164                         R_TimeReport("coronas");
7165         }
7166
7167 #if 0
7168         {
7169                 GL_DepthTest(false);
7170                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7171                 GL_Color(1, 1, 1, 1);
7172                 qglBegin(GL_POLYGON);
7173                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7174                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7175                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7176                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7177                 qglEnd();
7178                 qglBegin(GL_POLYGON);
7179                 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]);
7180                 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]);
7181                 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]);
7182                 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]);
7183                 qglEnd();
7184                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7185         }
7186 #endif
7187
7188         // don't let sound skip if going slow
7189         if (r_refdef.scene.extraupdate)
7190                 S_ExtraUpdate ();
7191 }
7192
7193 static const unsigned short bboxelements[36] =
7194 {
7195         5, 1, 3, 5, 3, 7,
7196         6, 2, 0, 6, 0, 4,
7197         7, 3, 2, 7, 2, 6,
7198         4, 0, 1, 4, 1, 5,
7199         4, 5, 7, 4, 7, 6,
7200         1, 0, 2, 1, 2, 3,
7201 };
7202
7203 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7204 {
7205         int i;
7206         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7207
7208         RSurf_ActiveWorldEntity();
7209
7210         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7211         GL_DepthMask(false);
7212         GL_DepthRange(0, 1);
7213         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7214 //      R_Mesh_ResetTextureState();
7215
7216         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7217         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7218         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7219         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7220         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7221         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7222         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7223         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7224         R_FillColors(color4f, 8, cr, cg, cb, ca);
7225         if (r_refdef.fogenabled)
7226         {
7227                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7228                 {
7229                         f1 = RSurf_FogVertex(v);
7230                         f2 = 1 - f1;
7231                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7232                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7233                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7234                 }
7235         }
7236         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7237         R_Mesh_ResetTextureState();
7238         R_SetupShader_Generic_NoTexture(false, false);
7239         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7240 }
7241
7242 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7243 {
7244         prvm_prog_t *prog = SVVM_prog;
7245         int i;
7246         float color[4];
7247         prvm_edict_t *edict;
7248
7249         // this function draws bounding boxes of server entities
7250         if (!sv.active)
7251                 return;
7252
7253         GL_CullFace(GL_NONE);
7254         R_SetupShader_Generic_NoTexture(false, false);
7255
7256         for (i = 0;i < numsurfaces;i++)
7257         {
7258                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7259                 switch ((int)PRVM_serveredictfloat(edict, solid))
7260                 {
7261                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7262                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7263                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7264                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7265                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7266                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7267                 }
7268                 color[3] *= r_showbboxes.value;
7269                 color[3] = bound(0, color[3], 1);
7270                 GL_DepthTest(!r_showdisabledepthtest.integer);
7271                 GL_CullFace(r_refdef.view.cullface_front);
7272                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7273         }
7274 }
7275
7276 static void R_DrawEntityBBoxes(void)
7277 {
7278         int i;
7279         prvm_edict_t *edict;
7280         vec3_t center;
7281         prvm_prog_t *prog = SVVM_prog;
7282
7283         // this function draws bounding boxes of server entities
7284         if (!sv.active)
7285                 return;
7286
7287         for (i = 0;i < prog->num_edicts;i++)
7288         {
7289                 edict = PRVM_EDICT_NUM(i);
7290                 if (edict->priv.server->free)
7291                         continue;
7292                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7293                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7294                         continue;
7295                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7296                         continue;
7297                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7298                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7299         }
7300 }
7301
7302 static const int nomodelelement3i[24] =
7303 {
7304         5, 2, 0,
7305         5, 1, 2,
7306         5, 0, 3,
7307         5, 3, 1,
7308         0, 2, 4,
7309         2, 1, 4,
7310         3, 0, 4,
7311         1, 3, 4
7312 };
7313
7314 static const unsigned short nomodelelement3s[24] =
7315 {
7316         5, 2, 0,
7317         5, 1, 2,
7318         5, 0, 3,
7319         5, 3, 1,
7320         0, 2, 4,
7321         2, 1, 4,
7322         3, 0, 4,
7323         1, 3, 4
7324 };
7325
7326 static const float nomodelvertex3f[6*3] =
7327 {
7328         -16,   0,   0,
7329          16,   0,   0,
7330           0, -16,   0,
7331           0,  16,   0,
7332           0,   0, -16,
7333           0,   0,  16
7334 };
7335
7336 static const float nomodelcolor4f[6*4] =
7337 {
7338         0.0f, 0.0f, 0.5f, 1.0f,
7339         0.0f, 0.0f, 0.5f, 1.0f,
7340         0.0f, 0.5f, 0.0f, 1.0f,
7341         0.0f, 0.5f, 0.0f, 1.0f,
7342         0.5f, 0.0f, 0.0f, 1.0f,
7343         0.5f, 0.0f, 0.0f, 1.0f
7344 };
7345
7346 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7347 {
7348         int i;
7349         float f1, f2, *c;
7350         float color4f[6*4];
7351
7352         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);
7353
7354         // this is only called once per entity so numsurfaces is always 1, and
7355         // surfacelist is always {0}, so this code does not handle batches
7356
7357         if (rsurface.ent_flags & RENDER_ADDITIVE)
7358         {
7359                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7360                 GL_DepthMask(false);
7361         }
7362         else if (rsurface.colormod[3] < 1)
7363         {
7364                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7365                 GL_DepthMask(false);
7366         }
7367         else
7368         {
7369                 GL_BlendFunc(GL_ONE, GL_ZERO);
7370                 GL_DepthMask(true);
7371         }
7372         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7373         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7374         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7375         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7376         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7377         for (i = 0, c = color4f;i < 6;i++, c += 4)
7378         {
7379                 c[0] *= rsurface.colormod[0];
7380                 c[1] *= rsurface.colormod[1];
7381                 c[2] *= rsurface.colormod[2];
7382                 c[3] *= rsurface.colormod[3];
7383         }
7384         if (r_refdef.fogenabled)
7385         {
7386                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7387                 {
7388                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7389                         f2 = 1 - f1;
7390                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7391                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7392                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7393                 }
7394         }
7395 //      R_Mesh_ResetTextureState();
7396         R_SetupShader_Generic_NoTexture(false, false);
7397         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7398         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7399 }
7400
7401 void R_DrawNoModel(entity_render_t *ent)
7402 {
7403         vec3_t org;
7404         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7405         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7406                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7407         else
7408                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7409 }
7410
7411 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7412 {
7413         vec3_t right1, right2, diff, normal;
7414
7415         VectorSubtract (org2, org1, normal);
7416
7417         // calculate 'right' vector for start
7418         VectorSubtract (r_refdef.view.origin, org1, diff);
7419         CrossProduct (normal, diff, right1);
7420         VectorNormalize (right1);
7421
7422         // calculate 'right' vector for end
7423         VectorSubtract (r_refdef.view.origin, org2, diff);
7424         CrossProduct (normal, diff, right2);
7425         VectorNormalize (right2);
7426
7427         vert[ 0] = org1[0] + width * right1[0];
7428         vert[ 1] = org1[1] + width * right1[1];
7429         vert[ 2] = org1[2] + width * right1[2];
7430         vert[ 3] = org1[0] - width * right1[0];
7431         vert[ 4] = org1[1] - width * right1[1];
7432         vert[ 5] = org1[2] - width * right1[2];
7433         vert[ 6] = org2[0] - width * right2[0];
7434         vert[ 7] = org2[1] - width * right2[1];
7435         vert[ 8] = org2[2] - width * right2[2];
7436         vert[ 9] = org2[0] + width * right2[0];
7437         vert[10] = org2[1] + width * right2[1];
7438         vert[11] = org2[2] + width * right2[2];
7439 }
7440
7441 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)
7442 {
7443         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7444         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7445         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7446         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7447         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7448         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7449         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7450         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7451         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7452         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7453         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7454         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7455 }
7456
7457 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7458 {
7459         int i;
7460         float *vertex3f;
7461         float v[3];
7462         VectorSet(v, x, y, z);
7463         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7464                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7465                         break;
7466         if (i == mesh->numvertices)
7467         {
7468                 if (mesh->numvertices < mesh->maxvertices)
7469                 {
7470                         VectorCopy(v, vertex3f);
7471                         mesh->numvertices++;
7472                 }
7473                 return mesh->numvertices;
7474         }
7475         else
7476                 return i;
7477 }
7478
7479 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7480 {
7481         int i;
7482         int *e, element[3];
7483         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7484         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7485         e = mesh->element3i + mesh->numtriangles * 3;
7486         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7487         {
7488                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7489                 if (mesh->numtriangles < mesh->maxtriangles)
7490                 {
7491                         *e++ = element[0];
7492                         *e++ = element[1];
7493                         *e++ = element[2];
7494                         mesh->numtriangles++;
7495                 }
7496                 element[1] = element[2];
7497         }
7498 }
7499
7500 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7501 {
7502         int i;
7503         int *e, element[3];
7504         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7505         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7506         e = mesh->element3i + mesh->numtriangles * 3;
7507         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7508         {
7509                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7510                 if (mesh->numtriangles < mesh->maxtriangles)
7511                 {
7512                         *e++ = element[0];
7513                         *e++ = element[1];
7514                         *e++ = element[2];
7515                         mesh->numtriangles++;
7516                 }
7517                 element[1] = element[2];
7518         }
7519 }
7520
7521 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7522 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7523 {
7524         int planenum, planenum2;
7525         int w;
7526         int tempnumpoints;
7527         mplane_t *plane, *plane2;
7528         double maxdist;
7529         double temppoints[2][256*3];
7530         // figure out how large a bounding box we need to properly compute this brush
7531         maxdist = 0;
7532         for (w = 0;w < numplanes;w++)
7533                 maxdist = max(maxdist, fabs(planes[w].dist));
7534         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7535         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7536         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7537         {
7538                 w = 0;
7539                 tempnumpoints = 4;
7540                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7541                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7542                 {
7543                         if (planenum2 == planenum)
7544                                 continue;
7545                         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);
7546                         w = !w;
7547                 }
7548                 if (tempnumpoints < 3)
7549                         continue;
7550                 // generate elements forming a triangle fan for this polygon
7551                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7552         }
7553 }
7554
7555 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)
7556 {
7557         texturelayer_t *layer;
7558         layer = t->currentlayers + t->currentnumlayers++;
7559         layer->type = type;
7560         layer->depthmask = depthmask;
7561         layer->blendfunc1 = blendfunc1;
7562         layer->blendfunc2 = blendfunc2;
7563         layer->texture = texture;
7564         layer->texmatrix = *matrix;
7565         layer->color[0] = r;
7566         layer->color[1] = g;
7567         layer->color[2] = b;
7568         layer->color[3] = a;
7569 }
7570
7571 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7572 {
7573         if(parms[0] == 0 && parms[1] == 0)
7574                 return false;
7575         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7576                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7577                         return false;
7578         return true;
7579 }
7580
7581 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7582 {
7583         double index, f;
7584         index = parms[2] + rsurface.shadertime * parms[3];
7585         index -= floor(index);
7586         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7587         {
7588         default:
7589         case Q3WAVEFUNC_NONE:
7590         case Q3WAVEFUNC_NOISE:
7591         case Q3WAVEFUNC_COUNT:
7592                 f = 0;
7593                 break;
7594         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7595         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7596         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7597         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7598         case Q3WAVEFUNC_TRIANGLE:
7599                 index *= 4;
7600                 f = index - floor(index);
7601                 if (index < 1)
7602                 {
7603                         // f = f;
7604                 }
7605                 else if (index < 2)
7606                         f = 1 - f;
7607                 else if (index < 3)
7608                         f = -f;
7609                 else
7610                         f = -(1 - f);
7611                 break;
7612         }
7613         f = parms[0] + parms[1] * f;
7614         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7615                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7616         return (float) f;
7617 }
7618
7619 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7620 {
7621         int w, h, idx;
7622         double f;
7623         double offsetd[2];
7624         float tcmat[12];
7625         matrix4x4_t matrix, temp;
7626         switch(tcmod->tcmod)
7627         {
7628                 case Q3TCMOD_COUNT:
7629                 case Q3TCMOD_NONE:
7630                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7631                                 matrix = r_waterscrollmatrix;
7632                         else
7633                                 matrix = identitymatrix;
7634                         break;
7635                 case Q3TCMOD_ENTITYTRANSLATE:
7636                         // this is used in Q3 to allow the gamecode to control texcoord
7637                         // scrolling on the entity, which is not supported in darkplaces yet.
7638                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7639                         break;
7640                 case Q3TCMOD_ROTATE:
7641                         f = tcmod->parms[0] * rsurface.shadertime;
7642                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7643                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7644                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7645                         break;
7646                 case Q3TCMOD_SCALE:
7647                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7648                         break;
7649                 case Q3TCMOD_SCROLL:
7650                         // extra care is needed because of precision breakdown with large values of time
7651                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7652                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7653                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7654                         break;
7655                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7656                         w = (int) tcmod->parms[0];
7657                         h = (int) tcmod->parms[1];
7658                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7659                         f = f - floor(f);
7660                         idx = (int) floor(f * w * h);
7661                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7662                         break;
7663                 case Q3TCMOD_STRETCH:
7664                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7665                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7666                         break;
7667                 case Q3TCMOD_TRANSFORM:
7668                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7669                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7670                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7671                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7672                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7673                         break;
7674                 case Q3TCMOD_TURBULENT:
7675                         // this is handled in the RSurf_PrepareVertices function
7676                         matrix = identitymatrix;
7677                         break;
7678         }
7679         temp = *texmatrix;
7680         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7681 }
7682
7683 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7684 {
7685         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7686         char name[MAX_QPATH];
7687         skinframe_t *skinframe;
7688         unsigned char pixels[296*194];
7689         strlcpy(cache->name, skinname, sizeof(cache->name));
7690         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7691         if (developer_loading.integer)
7692                 Con_Printf("loading %s\n", name);
7693         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7694         if (!skinframe || !skinframe->base)
7695         {
7696                 unsigned char *f;
7697                 fs_offset_t filesize;
7698                 skinframe = NULL;
7699                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7700                 if (f)
7701                 {
7702                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7703                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7704                         Mem_Free(f);
7705                 }
7706         }
7707         cache->skinframe = skinframe;
7708 }
7709
7710 texture_t *R_GetCurrentTexture(texture_t *t)
7711 {
7712         int i;
7713         const entity_render_t *ent = rsurface.entity;
7714         dp_model_t *model = ent->model;
7715         q3shaderinfo_layer_tcmod_t *tcmod;
7716
7717         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7718                 return t->currentframe;
7719         t->update_lastrenderframe = r_textureframe;
7720         t->update_lastrenderentity = (void *)ent;
7721
7722         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7723                 t->camera_entity = ent->entitynumber;
7724         else
7725                 t->camera_entity = 0;
7726
7727         // switch to an alternate material if this is a q1bsp animated material
7728         {
7729                 texture_t *texture = t;
7730                 int s = rsurface.ent_skinnum;
7731                 if ((unsigned int)s >= (unsigned int)model->numskins)
7732                         s = 0;
7733                 if (model->skinscenes)
7734                 {
7735                         if (model->skinscenes[s].framecount > 1)
7736                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7737                         else
7738                                 s = model->skinscenes[s].firstframe;
7739                 }
7740                 if (s > 0)
7741                         t = t + s * model->num_surfaces;
7742                 if (t->animated)
7743                 {
7744                         // use an alternate animation if the entity's frame is not 0,
7745                         // and only if the texture has an alternate animation
7746                         if (rsurface.ent_alttextures && t->anim_total[1])
7747                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7748                         else
7749                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7750                 }
7751                 texture->currentframe = t;
7752         }
7753
7754         // update currentskinframe to be a qw skin or animation frame
7755         if (rsurface.ent_qwskin >= 0)
7756         {
7757                 i = rsurface.ent_qwskin;
7758                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7759                 {
7760                         r_qwskincache_size = cl.maxclients;
7761                         if (r_qwskincache)
7762                                 Mem_Free(r_qwskincache);
7763                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7764                 }
7765                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7766                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7767                 t->currentskinframe = r_qwskincache[i].skinframe;
7768                 if (t->currentskinframe == NULL)
7769                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7770         }
7771         else if (t->numskinframes >= 2)
7772                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7773         if (t->backgroundnumskinframes >= 2)
7774                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7775
7776         t->currentmaterialflags = t->basematerialflags;
7777         t->currentalpha = rsurface.colormod[3];
7778         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7779                 t->currentalpha *= r_wateralpha.value;
7780         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7781                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7782         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7783                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7784         if (!(rsurface.ent_flags & RENDER_LIGHT))
7785                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7786         else if (FAKELIGHT_ENABLED)
7787         {
7788                 // no modellight if using fakelight for the map
7789         }
7790         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7791         {
7792                 // pick a model lighting mode
7793                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7794                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7795                 else
7796                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7797         }
7798         if (rsurface.ent_flags & RENDER_ADDITIVE)
7799                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7800         else if (t->currentalpha < 1)
7801                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7802         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7803         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7804                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7805         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7806                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7807         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7808                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7809         if (t->backgroundnumskinframes)
7810                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7811         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7812         {
7813                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7814                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7815         }
7816         else
7817                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7818         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7819         {
7820                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7821                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7822         }
7823         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7824                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7825
7826         // there is no tcmod
7827         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7828         {
7829                 t->currenttexmatrix = r_waterscrollmatrix;
7830                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7831         }
7832         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7833         {
7834                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7835                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7836         }
7837
7838         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7839                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7840         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7841                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7842
7843         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7844         if (t->currentskinframe->qpixels)
7845                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7846         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7847         if (!t->basetexture)
7848                 t->basetexture = r_texture_notexture;
7849         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7850         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7851         t->nmaptexture = t->currentskinframe->nmap;
7852         if (!t->nmaptexture)
7853                 t->nmaptexture = r_texture_blanknormalmap;
7854         t->glosstexture = r_texture_black;
7855         t->glowtexture = t->currentskinframe->glow;
7856         t->fogtexture = t->currentskinframe->fog;
7857         t->reflectmasktexture = t->currentskinframe->reflect;
7858         if (t->backgroundnumskinframes)
7859         {
7860                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7861                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7862                 t->backgroundglosstexture = r_texture_black;
7863                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7864                 if (!t->backgroundnmaptexture)
7865                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7866         }
7867         else
7868         {
7869                 t->backgroundbasetexture = r_texture_white;
7870                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7871                 t->backgroundglosstexture = r_texture_black;
7872                 t->backgroundglowtexture = NULL;
7873         }
7874         t->specularpower = r_shadow_glossexponent.value;
7875         // TODO: store reference values for these in the texture?
7876         t->specularscale = 0;
7877         if (r_shadow_gloss.integer > 0)
7878         {
7879                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7880                 {
7881                         if (r_shadow_glossintensity.value > 0)
7882                         {
7883                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7884                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7885                                 t->specularscale = r_shadow_glossintensity.value;
7886                         }
7887                 }
7888                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7889                 {
7890                         t->glosstexture = r_texture_white;
7891                         t->backgroundglosstexture = r_texture_white;
7892                         t->specularscale = r_shadow_gloss2intensity.value;
7893                         t->specularpower = r_shadow_gloss2exponent.value;
7894                 }
7895         }
7896         t->specularscale *= t->specularscalemod;
7897         t->specularpower *= t->specularpowermod;
7898         t->rtlightambient = 0;
7899
7900         // lightmaps mode looks bad with dlights using actual texturing, so turn
7901         // off the colormap and glossmap, but leave the normalmap on as it still
7902         // accurately represents the shading involved
7903         if (gl_lightmaps.integer)
7904         {
7905                 t->basetexture = r_texture_grey128;
7906                 t->pantstexture = r_texture_black;
7907                 t->shirttexture = r_texture_black;
7908                 t->nmaptexture = r_texture_blanknormalmap;
7909                 t->glosstexture = r_texture_black;
7910                 t->glowtexture = NULL;
7911                 t->fogtexture = NULL;
7912                 t->reflectmasktexture = NULL;
7913                 t->backgroundbasetexture = NULL;
7914                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7915                 t->backgroundglosstexture = r_texture_black;
7916                 t->backgroundglowtexture = NULL;
7917                 t->specularscale = 0;
7918                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7919         }
7920
7921         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7922         VectorClear(t->dlightcolor);
7923         t->currentnumlayers = 0;
7924         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7925         {
7926                 int blendfunc1, blendfunc2;
7927                 qboolean depthmask;
7928                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7929                 {
7930                         blendfunc1 = GL_SRC_ALPHA;
7931                         blendfunc2 = GL_ONE;
7932                 }
7933                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7934                 {
7935                         blendfunc1 = GL_SRC_ALPHA;
7936                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7937                 }
7938                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7939                 {
7940                         blendfunc1 = t->customblendfunc[0];
7941                         blendfunc2 = t->customblendfunc[1];
7942                 }
7943                 else
7944                 {
7945                         blendfunc1 = GL_ONE;
7946                         blendfunc2 = GL_ZERO;
7947                 }
7948                 // don't colormod evilblend textures
7949                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7950                         VectorSet(t->lightmapcolor, 1, 1, 1);
7951                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7952                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7953                 {
7954                         // fullbright is not affected by r_refdef.lightmapintensity
7955                         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]);
7956                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7957                                 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]);
7958                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7959                                 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]);
7960                 }
7961                 else
7962                 {
7963                         vec3_t ambientcolor;
7964                         float colorscale;
7965                         // set the color tint used for lights affecting this surface
7966                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7967                         colorscale = 2;
7968                         // q3bsp has no lightmap updates, so the lightstylevalue that
7969                         // would normally be baked into the lightmap must be
7970                         // applied to the color
7971                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7972                         if (model->type == mod_brushq3)
7973                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7974                         colorscale *= r_refdef.lightmapintensity;
7975                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7976                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7977                         // basic lit geometry
7978                         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]);
7979                         // add pants/shirt if needed
7980                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7981                                 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]);
7982                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7983                                 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]);
7984                         // now add ambient passes if needed
7985                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7986                         {
7987                                 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]);
7988                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7989                                         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]);
7990                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7991                                         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]);
7992                         }
7993                 }
7994                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7995                         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]);
7996                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7997                 {
7998                         // if this is opaque use alpha blend which will darken the earlier
7999                         // passes cheaply.
8000                         //
8001                         // if this is an alpha blended material, all the earlier passes
8002                         // were darkened by fog already, so we only need to add the fog
8003                         // color ontop through the fog mask texture
8004                         //
8005                         // if this is an additive blended material, all the earlier passes
8006                         // were darkened by fog already, and we should not add fog color
8007                         // (because the background was not darkened, there is no fog color
8008                         // that was lost behind it).
8009                         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]);
8010                 }
8011         }
8012
8013         return t->currentframe;
8014 }
8015
8016 rsurfacestate_t rsurface;
8017
8018 void RSurf_ActiveWorldEntity(void)
8019 {
8020         dp_model_t *model = r_refdef.scene.worldmodel;
8021         //if (rsurface.entity == r_refdef.scene.worldentity)
8022         //      return;
8023         rsurface.entity = r_refdef.scene.worldentity;
8024         rsurface.skeleton = NULL;
8025         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8026         rsurface.ent_skinnum = 0;
8027         rsurface.ent_qwskin = -1;
8028         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8029         rsurface.shadertime = r_refdef.scene.time;
8030         rsurface.matrix = identitymatrix;
8031         rsurface.inversematrix = identitymatrix;
8032         rsurface.matrixscale = 1;
8033         rsurface.inversematrixscale = 1;
8034         R_EntityMatrix(&identitymatrix);
8035         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8036         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8037         rsurface.fograngerecip = r_refdef.fograngerecip;
8038         rsurface.fogheightfade = r_refdef.fogheightfade;
8039         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8040         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8041         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8042         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8043         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8044         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8045         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8046         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8047         rsurface.colormod[3] = 1;
8048         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);
8049         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8050         rsurface.frameblend[0].lerp = 1;
8051         rsurface.ent_alttextures = false;
8052         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8053         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8054         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8055         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8056         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8057         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8058         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8059         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8060         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8061         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8062         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8063         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8064         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8065         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8066         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8067         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8068         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8069         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8070         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8071         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8072         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8073         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8074         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8075         rsurface.modelelement3i = model->surfmesh.data_element3i;
8076         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8077         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8078         rsurface.modelelement3s = model->surfmesh.data_element3s;
8079         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8080         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8081         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8082         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8083         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8084         rsurface.modelsurfaces = model->data_surfaces;
8085         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8086         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8087         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8088         rsurface.modelgeneratedvertex = false;
8089         rsurface.batchgeneratedvertex = false;
8090         rsurface.batchfirstvertex = 0;
8091         rsurface.batchnumvertices = 0;
8092         rsurface.batchfirsttriangle = 0;
8093         rsurface.batchnumtriangles = 0;
8094         rsurface.batchvertex3f  = NULL;
8095         rsurface.batchvertex3f_vertexbuffer = NULL;
8096         rsurface.batchvertex3f_bufferoffset = 0;
8097         rsurface.batchsvector3f = NULL;
8098         rsurface.batchsvector3f_vertexbuffer = NULL;
8099         rsurface.batchsvector3f_bufferoffset = 0;
8100         rsurface.batchtvector3f = NULL;
8101         rsurface.batchtvector3f_vertexbuffer = NULL;
8102         rsurface.batchtvector3f_bufferoffset = 0;
8103         rsurface.batchnormal3f  = NULL;
8104         rsurface.batchnormal3f_vertexbuffer = NULL;
8105         rsurface.batchnormal3f_bufferoffset = 0;
8106         rsurface.batchlightmapcolor4f = NULL;
8107         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8108         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8109         rsurface.batchtexcoordtexture2f = NULL;
8110         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8111         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8112         rsurface.batchtexcoordlightmap2f = NULL;
8113         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8114         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8115         rsurface.batchvertexmesh = NULL;
8116         rsurface.batchvertexmeshbuffer = NULL;
8117         rsurface.batchvertex3fbuffer = NULL;
8118         rsurface.batchelement3i = NULL;
8119         rsurface.batchelement3i_indexbuffer = NULL;
8120         rsurface.batchelement3i_bufferoffset = 0;
8121         rsurface.batchelement3s = NULL;
8122         rsurface.batchelement3s_indexbuffer = NULL;
8123         rsurface.batchelement3s_bufferoffset = 0;
8124         rsurface.passcolor4f = NULL;
8125         rsurface.passcolor4f_vertexbuffer = NULL;
8126         rsurface.passcolor4f_bufferoffset = 0;
8127 }
8128
8129 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8130 {
8131         dp_model_t *model = ent->model;
8132         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8133         //      return;
8134         rsurface.entity = (entity_render_t *)ent;
8135         rsurface.skeleton = ent->skeleton;
8136         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8137         rsurface.ent_skinnum = ent->skinnum;
8138         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;
8139         rsurface.ent_flags = ent->flags;
8140         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8141         rsurface.matrix = ent->matrix;
8142         rsurface.inversematrix = ent->inversematrix;
8143         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8144         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8145         R_EntityMatrix(&rsurface.matrix);
8146         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8147         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8148         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8149         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8150         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8151         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8152         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8153         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8154         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8155         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8156         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8157         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8158         rsurface.colormod[3] = ent->alpha;
8159         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8160         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8161         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8162         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8163         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8164         if (ent->model->brush.submodel && !prepass)
8165         {
8166                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8167                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8168         }
8169         if (model->surfmesh.isanimated && model->AnimateVertices)
8170         {
8171                 if (ent->animcache_vertex3f)
8172                 {
8173                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8174                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8175                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8176                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8177                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8178                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8179                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8180                 }
8181                 else if (wanttangents)
8182                 {
8183                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8184                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8185                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8186                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8187                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8188                         rsurface.modelvertexmesh = NULL;
8189                         rsurface.modelvertexmeshbuffer = NULL;
8190                         rsurface.modelvertex3fbuffer = NULL;
8191                 }
8192                 else if (wantnormals)
8193                 {
8194                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8195                         rsurface.modelsvector3f = NULL;
8196                         rsurface.modeltvector3f = NULL;
8197                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8198                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8199                         rsurface.modelvertexmesh = NULL;
8200                         rsurface.modelvertexmeshbuffer = NULL;
8201                         rsurface.modelvertex3fbuffer = NULL;
8202                 }
8203                 else
8204                 {
8205                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8206                         rsurface.modelsvector3f = NULL;
8207                         rsurface.modeltvector3f = NULL;
8208                         rsurface.modelnormal3f = NULL;
8209                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8210                         rsurface.modelvertexmesh = NULL;
8211                         rsurface.modelvertexmeshbuffer = NULL;
8212                         rsurface.modelvertex3fbuffer = NULL;
8213                 }
8214                 rsurface.modelvertex3f_vertexbuffer = 0;
8215                 rsurface.modelvertex3f_bufferoffset = 0;
8216                 rsurface.modelsvector3f_vertexbuffer = 0;
8217                 rsurface.modelsvector3f_bufferoffset = 0;
8218                 rsurface.modeltvector3f_vertexbuffer = 0;
8219                 rsurface.modeltvector3f_bufferoffset = 0;
8220                 rsurface.modelnormal3f_vertexbuffer = 0;
8221                 rsurface.modelnormal3f_bufferoffset = 0;
8222                 rsurface.modelgeneratedvertex = true;
8223         }
8224         else
8225         {
8226                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8227                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8228                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8229                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8230                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8231                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8232                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8233                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8234                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8235                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8236                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8237                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8238                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8239                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8240                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8241                 rsurface.modelgeneratedvertex = false;
8242         }
8243         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8244         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8245         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8246         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8247         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8248         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8249         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8250         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8251         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8252         rsurface.modelelement3i = model->surfmesh.data_element3i;
8253         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8254         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8255         rsurface.modelelement3s = model->surfmesh.data_element3s;
8256         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8257         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8258         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8259         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8260         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8261         rsurface.modelsurfaces = model->data_surfaces;
8262         rsurface.batchgeneratedvertex = false;
8263         rsurface.batchfirstvertex = 0;
8264         rsurface.batchnumvertices = 0;
8265         rsurface.batchfirsttriangle = 0;
8266         rsurface.batchnumtriangles = 0;
8267         rsurface.batchvertex3f  = NULL;
8268         rsurface.batchvertex3f_vertexbuffer = NULL;
8269         rsurface.batchvertex3f_bufferoffset = 0;
8270         rsurface.batchsvector3f = NULL;
8271         rsurface.batchsvector3f_vertexbuffer = NULL;
8272         rsurface.batchsvector3f_bufferoffset = 0;
8273         rsurface.batchtvector3f = NULL;
8274         rsurface.batchtvector3f_vertexbuffer = NULL;
8275         rsurface.batchtvector3f_bufferoffset = 0;
8276         rsurface.batchnormal3f  = NULL;
8277         rsurface.batchnormal3f_vertexbuffer = NULL;
8278         rsurface.batchnormal3f_bufferoffset = 0;
8279         rsurface.batchlightmapcolor4f = NULL;
8280         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8281         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8282         rsurface.batchtexcoordtexture2f = NULL;
8283         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8284         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8285         rsurface.batchtexcoordlightmap2f = NULL;
8286         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8287         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8288         rsurface.batchvertexmesh = NULL;
8289         rsurface.batchvertexmeshbuffer = NULL;
8290         rsurface.batchvertex3fbuffer = NULL;
8291         rsurface.batchelement3i = NULL;
8292         rsurface.batchelement3i_indexbuffer = NULL;
8293         rsurface.batchelement3i_bufferoffset = 0;
8294         rsurface.batchelement3s = NULL;
8295         rsurface.batchelement3s_indexbuffer = NULL;
8296         rsurface.batchelement3s_bufferoffset = 0;
8297         rsurface.passcolor4f = NULL;
8298         rsurface.passcolor4f_vertexbuffer = NULL;
8299         rsurface.passcolor4f_bufferoffset = 0;
8300 }
8301
8302 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)
8303 {
8304         rsurface.entity = r_refdef.scene.worldentity;
8305         rsurface.skeleton = NULL;
8306         rsurface.ent_skinnum = 0;
8307         rsurface.ent_qwskin = -1;
8308         rsurface.ent_flags = entflags;
8309         rsurface.shadertime = r_refdef.scene.time - shadertime;
8310         rsurface.modelnumvertices = numvertices;
8311         rsurface.modelnumtriangles = numtriangles;
8312         rsurface.matrix = *matrix;
8313         rsurface.inversematrix = *inversematrix;
8314         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8315         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8316         R_EntityMatrix(&rsurface.matrix);
8317         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8318         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8319         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8320         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8321         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8322         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8323         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8324         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8325         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8326         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8327         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8328         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8329         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);
8330         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8331         rsurface.frameblend[0].lerp = 1;
8332         rsurface.ent_alttextures = false;
8333         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8334         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8335         if (wanttangents)
8336         {
8337                 rsurface.modelvertex3f = (float *)vertex3f;
8338                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8339                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8340                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8341         }
8342         else if (wantnormals)
8343         {
8344                 rsurface.modelvertex3f = (float *)vertex3f;
8345                 rsurface.modelsvector3f = NULL;
8346                 rsurface.modeltvector3f = NULL;
8347                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8348         }
8349         else
8350         {
8351                 rsurface.modelvertex3f = (float *)vertex3f;
8352                 rsurface.modelsvector3f = NULL;
8353                 rsurface.modeltvector3f = NULL;
8354                 rsurface.modelnormal3f = NULL;
8355         }
8356         rsurface.modelvertexmesh = NULL;
8357         rsurface.modelvertexmeshbuffer = NULL;
8358         rsurface.modelvertex3fbuffer = NULL;
8359         rsurface.modelvertex3f_vertexbuffer = 0;
8360         rsurface.modelvertex3f_bufferoffset = 0;
8361         rsurface.modelsvector3f_vertexbuffer = 0;
8362         rsurface.modelsvector3f_bufferoffset = 0;
8363         rsurface.modeltvector3f_vertexbuffer = 0;
8364         rsurface.modeltvector3f_bufferoffset = 0;
8365         rsurface.modelnormal3f_vertexbuffer = 0;
8366         rsurface.modelnormal3f_bufferoffset = 0;
8367         rsurface.modelgeneratedvertex = true;
8368         rsurface.modellightmapcolor4f  = (float *)color4f;
8369         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8370         rsurface.modellightmapcolor4f_bufferoffset = 0;
8371         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8372         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8373         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8374         rsurface.modeltexcoordlightmap2f  = NULL;
8375         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8376         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8377         rsurface.modelelement3i = (int *)element3i;
8378         rsurface.modelelement3i_indexbuffer = NULL;
8379         rsurface.modelelement3i_bufferoffset = 0;
8380         rsurface.modelelement3s = (unsigned short *)element3s;
8381         rsurface.modelelement3s_indexbuffer = NULL;
8382         rsurface.modelelement3s_bufferoffset = 0;
8383         rsurface.modellightmapoffsets = NULL;
8384         rsurface.modelsurfaces = NULL;
8385         rsurface.batchgeneratedvertex = false;
8386         rsurface.batchfirstvertex = 0;
8387         rsurface.batchnumvertices = 0;
8388         rsurface.batchfirsttriangle = 0;
8389         rsurface.batchnumtriangles = 0;
8390         rsurface.batchvertex3f  = NULL;
8391         rsurface.batchvertex3f_vertexbuffer = NULL;
8392         rsurface.batchvertex3f_bufferoffset = 0;
8393         rsurface.batchsvector3f = NULL;
8394         rsurface.batchsvector3f_vertexbuffer = NULL;
8395         rsurface.batchsvector3f_bufferoffset = 0;
8396         rsurface.batchtvector3f = NULL;
8397         rsurface.batchtvector3f_vertexbuffer = NULL;
8398         rsurface.batchtvector3f_bufferoffset = 0;
8399         rsurface.batchnormal3f  = NULL;
8400         rsurface.batchnormal3f_vertexbuffer = NULL;
8401         rsurface.batchnormal3f_bufferoffset = 0;
8402         rsurface.batchlightmapcolor4f = NULL;
8403         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8404         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8405         rsurface.batchtexcoordtexture2f = NULL;
8406         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8407         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8408         rsurface.batchtexcoordlightmap2f = NULL;
8409         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8410         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8411         rsurface.batchvertexmesh = NULL;
8412         rsurface.batchvertexmeshbuffer = NULL;
8413         rsurface.batchvertex3fbuffer = NULL;
8414         rsurface.batchelement3i = NULL;
8415         rsurface.batchelement3i_indexbuffer = NULL;
8416         rsurface.batchelement3i_bufferoffset = 0;
8417         rsurface.batchelement3s = NULL;
8418         rsurface.batchelement3s_indexbuffer = NULL;
8419         rsurface.batchelement3s_bufferoffset = 0;
8420         rsurface.passcolor4f = NULL;
8421         rsurface.passcolor4f_vertexbuffer = NULL;
8422         rsurface.passcolor4f_bufferoffset = 0;
8423
8424         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8425         {
8426                 if ((wantnormals || wanttangents) && !normal3f)
8427                 {
8428                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8429                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8430                 }
8431                 if (wanttangents && !svector3f)
8432                 {
8433                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8434                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8435                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8436                 }
8437         }
8438 }
8439
8440 float RSurf_FogPoint(const float *v)
8441 {
8442         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8443         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8444         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8445         float FogHeightFade = r_refdef.fogheightfade;
8446         float fogfrac;
8447         unsigned int fogmasktableindex;
8448         if (r_refdef.fogplaneviewabove)
8449                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8450         else
8451                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8452         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8453         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8454 }
8455
8456 float RSurf_FogVertex(const float *v)
8457 {
8458         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8459         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8460         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8461         float FogHeightFade = rsurface.fogheightfade;
8462         float fogfrac;
8463         unsigned int fogmasktableindex;
8464         if (r_refdef.fogplaneviewabove)
8465                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8466         else
8467                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8468         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8469         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8470 }
8471
8472 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8473 {
8474         int i;
8475         for (i = 0;i < numelements;i++)
8476                 outelement3i[i] = inelement3i[i] + adjust;
8477 }
8478
8479 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8480 extern cvar_t gl_vbo;
8481 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8482 {
8483         int deformindex;
8484         int firsttriangle;
8485         int numtriangles;
8486         int firstvertex;
8487         int endvertex;
8488         int numvertices;
8489         int surfacefirsttriangle;
8490         int surfacenumtriangles;
8491         int surfacefirstvertex;
8492         int surfaceendvertex;
8493         int surfacenumvertices;
8494         int batchnumvertices;
8495         int batchnumtriangles;
8496         int needsupdate;
8497         int i, j;
8498         qboolean gaps;
8499         qboolean dynamicvertex;
8500         float amplitude;
8501         float animpos;
8502         float scale;
8503         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8504         float waveparms[4];
8505         q3shaderinfo_deform_t *deform;
8506         const msurface_t *surface, *firstsurface;
8507         r_vertexmesh_t *vertexmesh;
8508         if (!texturenumsurfaces)
8509                 return;
8510         // find vertex range of this surface batch
8511         gaps = false;
8512         firstsurface = texturesurfacelist[0];
8513         firsttriangle = firstsurface->num_firsttriangle;
8514         batchnumvertices = 0;
8515         batchnumtriangles = 0;
8516         firstvertex = endvertex = firstsurface->num_firstvertex;
8517         for (i = 0;i < texturenumsurfaces;i++)
8518         {
8519                 surface = texturesurfacelist[i];
8520                 if (surface != firstsurface + i)
8521                         gaps = true;
8522                 surfacefirstvertex = surface->num_firstvertex;
8523                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8524                 surfacenumvertices = surface->num_vertices;
8525                 surfacenumtriangles = surface->num_triangles;
8526                 if (firstvertex > surfacefirstvertex)
8527                         firstvertex = surfacefirstvertex;
8528                 if (endvertex < surfaceendvertex)
8529                         endvertex = surfaceendvertex;
8530                 batchnumvertices += surfacenumvertices;
8531                 batchnumtriangles += surfacenumtriangles;
8532         }
8533
8534         // we now know the vertex range used, and if there are any gaps in it
8535         rsurface.batchfirstvertex = firstvertex;
8536         rsurface.batchnumvertices = endvertex - firstvertex;
8537         rsurface.batchfirsttriangle = firsttriangle;
8538         rsurface.batchnumtriangles = batchnumtriangles;
8539
8540         // this variable holds flags for which properties have been updated that
8541         // may require regenerating vertexmesh array...
8542         needsupdate = 0;
8543
8544         // check if any dynamic vertex processing must occur
8545         dynamicvertex = false;
8546
8547         // if there is a chance of animated vertex colors, it's a dynamic batch
8548         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8549         {
8550                 dynamicvertex = true;
8551                 batchneed |= BATCHNEED_NOGAPS;
8552                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8553         }
8554
8555         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8556         {
8557                 switch (deform->deform)
8558                 {
8559                 default:
8560                 case Q3DEFORM_PROJECTIONSHADOW:
8561                 case Q3DEFORM_TEXT0:
8562                 case Q3DEFORM_TEXT1:
8563                 case Q3DEFORM_TEXT2:
8564                 case Q3DEFORM_TEXT3:
8565                 case Q3DEFORM_TEXT4:
8566                 case Q3DEFORM_TEXT5:
8567                 case Q3DEFORM_TEXT6:
8568                 case Q3DEFORM_TEXT7:
8569                 case Q3DEFORM_NONE:
8570                         break;
8571                 case Q3DEFORM_AUTOSPRITE:
8572                         dynamicvertex = true;
8573                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8574                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8575                         break;
8576                 case Q3DEFORM_AUTOSPRITE2:
8577                         dynamicvertex = true;
8578                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8579                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8580                         break;
8581                 case Q3DEFORM_NORMAL:
8582                         dynamicvertex = true;
8583                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8584                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8585                         break;
8586                 case Q3DEFORM_WAVE:
8587                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8588                                 break; // if wavefunc is a nop, ignore this transform
8589                         dynamicvertex = true;
8590                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8591                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8592                         break;
8593                 case Q3DEFORM_BULGE:
8594                         dynamicvertex = true;
8595                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8596                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8597                         break;
8598                 case Q3DEFORM_MOVE:
8599                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8600                                 break; // if wavefunc is a nop, ignore this transform
8601                         dynamicvertex = true;
8602                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8603                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8604                         break;
8605                 }
8606         }
8607         switch(rsurface.texture->tcgen.tcgen)
8608         {
8609         default:
8610         case Q3TCGEN_TEXTURE:
8611                 break;
8612         case Q3TCGEN_LIGHTMAP:
8613                 dynamicvertex = true;
8614                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8615                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8616                 break;
8617         case Q3TCGEN_VECTOR:
8618                 dynamicvertex = true;
8619                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8620                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8621                 break;
8622         case Q3TCGEN_ENVIRONMENT:
8623                 dynamicvertex = true;
8624                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8625                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8626                 break;
8627         }
8628         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8629         {
8630                 dynamicvertex = true;
8631                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8632                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8633         }
8634
8635         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8636         {
8637                 dynamicvertex = true;
8638                 batchneed |= BATCHNEED_NOGAPS;
8639                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8640         }
8641
8642         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8643         {
8644                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8645                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8646                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8647                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8648                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8649                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8650                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8651         }
8652
8653         // when the model data has no vertex buffer (dynamic mesh), we need to
8654         // eliminate gaps
8655         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8656                 batchneed |= BATCHNEED_NOGAPS;
8657
8658         // if needsupdate, we have to do a dynamic vertex batch for sure
8659         if (needsupdate & batchneed)
8660                 dynamicvertex = true;
8661
8662         // see if we need to build vertexmesh from arrays
8663         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8664                 dynamicvertex = true;
8665
8666         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8667         // also some drivers strongly dislike firstvertex
8668         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8669                 dynamicvertex = true;
8670
8671         rsurface.batchvertex3f = rsurface.modelvertex3f;
8672         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8673         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8674         rsurface.batchsvector3f = rsurface.modelsvector3f;
8675         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8676         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8677         rsurface.batchtvector3f = rsurface.modeltvector3f;
8678         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8679         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8680         rsurface.batchnormal3f = rsurface.modelnormal3f;
8681         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8682         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8683         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8684         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8685         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8686         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8687         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8688         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8689         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8690         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8691         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8692         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8693         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8694         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8695         rsurface.batchelement3i = rsurface.modelelement3i;
8696         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8697         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8698         rsurface.batchelement3s = rsurface.modelelement3s;
8699         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8700         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8701
8702         // if any dynamic vertex processing has to occur in software, we copy the
8703         // entire surface list together before processing to rebase the vertices
8704         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8705         //
8706         // if any gaps exist and we do not have a static vertex buffer, we have to
8707         // copy the surface list together to avoid wasting upload bandwidth on the
8708         // vertices in the gaps.
8709         //
8710         // if gaps exist and we have a static vertex buffer, we still have to
8711         // combine the index buffer ranges into one dynamic index buffer.
8712         //
8713         // in all cases we end up with data that can be drawn in one call.
8714
8715         if (!dynamicvertex)
8716         {
8717                 // static vertex data, just set pointers...
8718                 rsurface.batchgeneratedvertex = false;
8719                 // if there are gaps, we want to build a combined index buffer,
8720                 // otherwise use the original static buffer with an appropriate offset
8721                 if (gaps)
8722                 {
8723                         // build a new triangle elements array for this batch
8724                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8725                         rsurface.batchfirsttriangle = 0;
8726                         numtriangles = 0;
8727                         for (i = 0;i < texturenumsurfaces;i++)
8728                         {
8729                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8730                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8731                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8732                                 numtriangles += surfacenumtriangles;
8733                         }
8734                         rsurface.batchelement3i_indexbuffer = NULL;
8735                         rsurface.batchelement3i_bufferoffset = 0;
8736                         rsurface.batchelement3s = NULL;
8737                         rsurface.batchelement3s_indexbuffer = NULL;
8738                         rsurface.batchelement3s_bufferoffset = 0;
8739                         if (endvertex <= 65536)
8740                         {
8741                                 // make a 16bit (unsigned short) index array if possible
8742                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8743                                 for (i = 0;i < numtriangles*3;i++)
8744                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8745                         }
8746                 }
8747                 return;
8748         }
8749
8750         // something needs software processing, do it for real...
8751         // we only directly handle separate array data in this case and then
8752         // generate interleaved data if needed...
8753         rsurface.batchgeneratedvertex = true;
8754
8755         // now copy the vertex data into a combined array and make an index array
8756         // (this is what Quake3 does all the time)
8757         //if (gaps || rsurface.batchfirstvertex)
8758         {
8759                 rsurface.batchvertex3fbuffer = NULL;
8760                 rsurface.batchvertexmesh = NULL;
8761                 rsurface.batchvertexmeshbuffer = NULL;
8762                 rsurface.batchvertex3f = NULL;
8763                 rsurface.batchvertex3f_vertexbuffer = NULL;
8764                 rsurface.batchvertex3f_bufferoffset = 0;
8765                 rsurface.batchsvector3f = NULL;
8766                 rsurface.batchsvector3f_vertexbuffer = NULL;
8767                 rsurface.batchsvector3f_bufferoffset = 0;
8768                 rsurface.batchtvector3f = NULL;
8769                 rsurface.batchtvector3f_vertexbuffer = NULL;
8770                 rsurface.batchtvector3f_bufferoffset = 0;
8771                 rsurface.batchnormal3f = NULL;
8772                 rsurface.batchnormal3f_vertexbuffer = NULL;
8773                 rsurface.batchnormal3f_bufferoffset = 0;
8774                 rsurface.batchlightmapcolor4f = NULL;
8775                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8776                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8777                 rsurface.batchtexcoordtexture2f = NULL;
8778                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8779                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8780                 rsurface.batchtexcoordlightmap2f = NULL;
8781                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8782                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8783                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8784                 rsurface.batchelement3i_indexbuffer = NULL;
8785                 rsurface.batchelement3i_bufferoffset = 0;
8786                 rsurface.batchelement3s = NULL;
8787                 rsurface.batchelement3s_indexbuffer = NULL;
8788                 rsurface.batchelement3s_bufferoffset = 0;
8789                 // we'll only be setting up certain arrays as needed
8790                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8791                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8792                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8793                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8795                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8796                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8797                 {
8798                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8799                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8800                 }
8801                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8802                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8803                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8804                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8805                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8806                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8807                 numvertices = 0;
8808                 numtriangles = 0;
8809                 for (i = 0;i < texturenumsurfaces;i++)
8810                 {
8811                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8812                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8813                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8814                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8815                         // copy only the data requested
8816                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8817                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8818                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8819                         {
8820                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8821                                 {
8822                                         if (rsurface.batchvertex3f)
8823                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8824                                         else
8825                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8826                                 }
8827                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8828                                 {
8829                                         if (rsurface.modelnormal3f)
8830                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8831                                         else
8832                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8833                                 }
8834                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8835                                 {
8836                                         if (rsurface.modelsvector3f)
8837                                         {
8838                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8839                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8840                                         }
8841                                         else
8842                                         {
8843                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8844                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8845                                         }
8846                                 }
8847                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8848                                 {
8849                                         if (rsurface.modellightmapcolor4f)
8850                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8851                                         else
8852                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8853                                 }
8854                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8855                                 {
8856                                         if (rsurface.modeltexcoordtexture2f)
8857                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8858                                         else
8859                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8860                                 }
8861                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8862                                 {
8863                                         if (rsurface.modeltexcoordlightmap2f)
8864                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8865                                         else
8866                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8867                                 }
8868                         }
8869                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8870                         numvertices += surfacenumvertices;
8871                         numtriangles += surfacenumtriangles;
8872                 }
8873
8874                 // generate a 16bit index array as well if possible
8875                 // (in general, dynamic batches fit)
8876                 if (numvertices <= 65536)
8877                 {
8878                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8879                         for (i = 0;i < numtriangles*3;i++)
8880                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8881                 }
8882
8883                 // since we've copied everything, the batch now starts at 0
8884                 rsurface.batchfirstvertex = 0;
8885                 rsurface.batchnumvertices = batchnumvertices;
8886                 rsurface.batchfirsttriangle = 0;
8887                 rsurface.batchnumtriangles = batchnumtriangles;
8888         }
8889
8890         // q1bsp surfaces rendered in vertex color mode have to have colors
8891         // calculated based on lightstyles
8892         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8893         {
8894                 // generate color arrays for the surfaces in this list
8895                 int c[4];
8896                 int scale;
8897                 int size3;
8898                 const int *offsets;
8899                 const unsigned char *lm;
8900                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8901                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8902                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8903                 numvertices = 0;
8904                 for (i = 0;i < texturenumsurfaces;i++)
8905                 {
8906                         surface = texturesurfacelist[i];
8907                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8908                         surfacenumvertices = surface->num_vertices;
8909                         if (surface->lightmapinfo->samples)
8910                         {
8911                                 for (j = 0;j < surfacenumvertices;j++)
8912                                 {
8913                                         lm = surface->lightmapinfo->samples + offsets[j];
8914                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8915                                         VectorScale(lm, scale, c);
8916                                         if (surface->lightmapinfo->styles[1] != 255)
8917                                         {
8918                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8919                                                 lm += size3;
8920                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8921                                                 VectorMA(c, scale, lm, c);
8922                                                 if (surface->lightmapinfo->styles[2] != 255)
8923                                                 {
8924                                                         lm += size3;
8925                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8926                                                         VectorMA(c, scale, lm, c);
8927                                                         if (surface->lightmapinfo->styles[3] != 255)
8928                                                         {
8929                                                                 lm += size3;
8930                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8931                                                                 VectorMA(c, scale, lm, c);
8932                                                         }
8933                                                 }
8934                                         }
8935                                         c[0] >>= 7;
8936                                         c[1] >>= 7;
8937                                         c[2] >>= 7;
8938                                         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);
8939                                         numvertices++;
8940                                 }
8941                         }
8942                         else
8943                         {
8944                                 for (j = 0;j < surfacenumvertices;j++)
8945                                 {
8946                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8947                                         numvertices++;
8948                                 }
8949                         }
8950                 }
8951         }
8952
8953         // if vertices are deformed (sprite flares and things in maps, possibly
8954         // water waves, bulges and other deformations), modify the copied vertices
8955         // in place
8956         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8957         {
8958                 switch (deform->deform)
8959                 {
8960                 default:
8961                 case Q3DEFORM_PROJECTIONSHADOW:
8962                 case Q3DEFORM_TEXT0:
8963                 case Q3DEFORM_TEXT1:
8964                 case Q3DEFORM_TEXT2:
8965                 case Q3DEFORM_TEXT3:
8966                 case Q3DEFORM_TEXT4:
8967                 case Q3DEFORM_TEXT5:
8968                 case Q3DEFORM_TEXT6:
8969                 case Q3DEFORM_TEXT7:
8970                 case Q3DEFORM_NONE:
8971                         break;
8972                 case Q3DEFORM_AUTOSPRITE:
8973                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8974                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8975                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8976                         VectorNormalize(newforward);
8977                         VectorNormalize(newright);
8978                         VectorNormalize(newup);
8979 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8980 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8981 //                      rsurface.batchvertex3f_bufferoffset = 0;
8982 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8983 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8984 //                      rsurface.batchsvector3f_bufferoffset = 0;
8985 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8986 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8987 //                      rsurface.batchtvector3f_bufferoffset = 0;
8988 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8989 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8990 //                      rsurface.batchnormal3f_bufferoffset = 0;
8991                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8992                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8993                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8994                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8995                                 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);
8996                         // a single autosprite surface can contain multiple sprites...
8997                         for (j = 0;j < batchnumvertices - 3;j += 4)
8998                         {
8999                                 VectorClear(center);
9000                                 for (i = 0;i < 4;i++)
9001                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9002                                 VectorScale(center, 0.25f, center);
9003                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9004                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9005                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9006                                 for (i = 0;i < 4;i++)
9007                                 {
9008                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9009                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9010                                 }
9011                         }
9012                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9013                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9014                         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);
9015                         break;
9016                 case Q3DEFORM_AUTOSPRITE2:
9017                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9018                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9019                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9020                         VectorNormalize(newforward);
9021                         VectorNormalize(newright);
9022                         VectorNormalize(newup);
9023 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9024 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9025 //                      rsurface.batchvertex3f_bufferoffset = 0;
9026                         {
9027                                 const float *v1, *v2;
9028                                 vec3_t start, end;
9029                                 float f, l;
9030                                 struct
9031                                 {
9032                                         float length2;
9033                                         const float *v1;
9034                                         const float *v2;
9035                                 }
9036                                 shortest[2];
9037                                 memset(shortest, 0, sizeof(shortest));
9038                                 // a single autosprite surface can contain multiple sprites...
9039                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9040                                 {
9041                                         VectorClear(center);
9042                                         for (i = 0;i < 4;i++)
9043                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9044                                         VectorScale(center, 0.25f, center);
9045                                         // find the two shortest edges, then use them to define the
9046                                         // axis vectors for rotating around the central axis
9047                                         for (i = 0;i < 6;i++)
9048                                         {
9049                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9050                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9051                                                 l = VectorDistance2(v1, v2);
9052                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9053                                                 if (v1[2] != v2[2])
9054                                                         l += (1.0f / 1024.0f);
9055                                                 if (shortest[0].length2 > l || i == 0)
9056                                                 {
9057                                                         shortest[1] = shortest[0];
9058                                                         shortest[0].length2 = l;
9059                                                         shortest[0].v1 = v1;
9060                                                         shortest[0].v2 = v2;
9061                                                 }
9062                                                 else if (shortest[1].length2 > l || i == 1)
9063                                                 {
9064                                                         shortest[1].length2 = l;
9065                                                         shortest[1].v1 = v1;
9066                                                         shortest[1].v2 = v2;
9067                                                 }
9068                                         }
9069                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9070                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9071                                         // this calculates the right vector from the shortest edge
9072                                         // and the up vector from the edge midpoints
9073                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9074                                         VectorNormalize(right);
9075                                         VectorSubtract(end, start, up);
9076                                         VectorNormalize(up);
9077                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9078                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9079                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9080                                         VectorNegate(forward, forward);
9081                                         VectorReflect(forward, 0, up, forward);
9082                                         VectorNormalize(forward);
9083                                         CrossProduct(up, forward, newright);
9084                                         VectorNormalize(newright);
9085                                         // rotate the quad around the up axis vector, this is made
9086                                         // especially easy by the fact we know the quad is flat,
9087                                         // so we only have to subtract the center position and
9088                                         // measure distance along the right vector, and then
9089                                         // multiply that by the newright vector and add back the
9090                                         // center position
9091                                         // we also need to subtract the old position to undo the
9092                                         // displacement from the center, which we do with a
9093                                         // DotProduct, the subtraction/addition of center is also
9094                                         // optimized into DotProducts here
9095                                         l = DotProduct(right, center);
9096                                         for (i = 0;i < 4;i++)
9097                                         {
9098                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9099                                                 f = DotProduct(right, v1) - l;
9100                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9101                                         }
9102                                 }
9103                         }
9104                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9105                         {
9106 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9107 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9108 //                              rsurface.batchnormal3f_bufferoffset = 0;
9109                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9110                         }
9111                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9112                         {
9113 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9114 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9115 //                              rsurface.batchsvector3f_bufferoffset = 0;
9116 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9117 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9118 //                              rsurface.batchtvector3f_bufferoffset = 0;
9119                                 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);
9120                         }
9121                         break;
9122                 case Q3DEFORM_NORMAL:
9123                         // deform the normals to make reflections wavey
9124                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9125                         rsurface.batchnormal3f_vertexbuffer = NULL;
9126                         rsurface.batchnormal3f_bufferoffset = 0;
9127                         for (j = 0;j < batchnumvertices;j++)
9128                         {
9129                                 float vertex[3];
9130                                 float *normal = rsurface.batchnormal3f + 3*j;
9131                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9132                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9133                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9134                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9135                                 VectorNormalize(normal);
9136                         }
9137                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9138                         {
9139 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9140 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9141 //                              rsurface.batchsvector3f_bufferoffset = 0;
9142 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9143 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9144 //                              rsurface.batchtvector3f_bufferoffset = 0;
9145                                 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);
9146                         }
9147                         break;
9148                 case Q3DEFORM_WAVE:
9149                         // deform vertex array to make wavey water and flags and such
9150                         waveparms[0] = deform->waveparms[0];
9151                         waveparms[1] = deform->waveparms[1];
9152                         waveparms[2] = deform->waveparms[2];
9153                         waveparms[3] = deform->waveparms[3];
9154                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9155                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9156                         // this is how a divisor of vertex influence on deformation
9157                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9158                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9159 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9160 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9161 //                      rsurface.batchvertex3f_bufferoffset = 0;
9162 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9163 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9164 //                      rsurface.batchnormal3f_bufferoffset = 0;
9165                         for (j = 0;j < batchnumvertices;j++)
9166                         {
9167                                 // if the wavefunc depends on time, evaluate it per-vertex
9168                                 if (waveparms[3])
9169                                 {
9170                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9171                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9172                                 }
9173                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9174                         }
9175                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9176                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9177                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9178                         {
9179 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9180 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9181 //                              rsurface.batchsvector3f_bufferoffset = 0;
9182 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9183 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9184 //                              rsurface.batchtvector3f_bufferoffset = 0;
9185                                 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);
9186                         }
9187                         break;
9188                 case Q3DEFORM_BULGE:
9189                         // deform vertex array to make the surface have moving bulges
9190 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9191 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9192 //                      rsurface.batchvertex3f_bufferoffset = 0;
9193 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9194 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9195 //                      rsurface.batchnormal3f_bufferoffset = 0;
9196                         for (j = 0;j < batchnumvertices;j++)
9197                         {
9198                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9199                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9200                         }
9201                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9202                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9203                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9204                         {
9205 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9206 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9207 //                              rsurface.batchsvector3f_bufferoffset = 0;
9208 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9209 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9210 //                              rsurface.batchtvector3f_bufferoffset = 0;
9211                                 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);
9212                         }
9213                         break;
9214                 case Q3DEFORM_MOVE:
9215                         // deform vertex array
9216                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9217                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9218                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9219                         VectorScale(deform->parms, scale, waveparms);
9220 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9221 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9222 //                      rsurface.batchvertex3f_bufferoffset = 0;
9223                         for (j = 0;j < batchnumvertices;j++)
9224                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9225                         break;
9226                 }
9227         }
9228
9229         // generate texcoords based on the chosen texcoord source
9230         switch(rsurface.texture->tcgen.tcgen)
9231         {
9232         default:
9233         case Q3TCGEN_TEXTURE:
9234                 break;
9235         case Q3TCGEN_LIGHTMAP:
9236 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9237 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9238 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9239                 if (rsurface.batchtexcoordlightmap2f)
9240                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9241                 break;
9242         case Q3TCGEN_VECTOR:
9243 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9244 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9245 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9246                 for (j = 0;j < batchnumvertices;j++)
9247                 {
9248                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9249                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9250                 }
9251                 break;
9252         case Q3TCGEN_ENVIRONMENT:
9253                 // make environment reflections using a spheremap
9254                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9255                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9256                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9257                 for (j = 0;j < batchnumvertices;j++)
9258                 {
9259                         // identical to Q3A's method, but executed in worldspace so
9260                         // carried models can be shiny too
9261
9262                         float viewer[3], d, reflected[3], worldreflected[3];
9263
9264                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9265                         // VectorNormalize(viewer);
9266
9267                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9268
9269                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9270                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9271                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9272                         // note: this is proportinal to viewer, so we can normalize later
9273
9274                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9275                         VectorNormalize(worldreflected);
9276
9277                         // note: this sphere map only uses world x and z!
9278                         // so positive and negative y will LOOK THE SAME.
9279                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9280                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9281                 }
9282                 break;
9283         }
9284         // the only tcmod that needs software vertex processing is turbulent, so
9285         // check for it here and apply the changes if needed
9286         // and we only support that as the first one
9287         // (handling a mixture of turbulent and other tcmods would be problematic
9288         //  without punting it entirely to a software path)
9289         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9290         {
9291                 amplitude = rsurface.texture->tcmods[0].parms[1];
9292                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9293 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9294 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9295 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9296                 for (j = 0;j < batchnumvertices;j++)
9297                 {
9298                         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);
9299                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9300                 }
9301         }
9302
9303         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9304         {
9305                 // convert the modified arrays to vertex structs
9306 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9307 //              rsurface.batchvertexmeshbuffer = NULL;
9308                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9309                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9310                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9311                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9312                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9313                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9314                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9315                 {
9316                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9317                         {
9318                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9319                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9320                         }
9321                 }
9322                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9323                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9324                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9325                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9326                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9327                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9328                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9329                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9330                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9331         }
9332 }
9333
9334 void RSurf_DrawBatch(void)
9335 {
9336         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9337         // through the pipeline, killing it earlier in the pipeline would have
9338         // per-surface overhead rather than per-batch overhead, so it's best to
9339         // reject it here, before it hits glDraw.
9340         if (rsurface.batchnumtriangles == 0)
9341                 return;
9342 #if 0
9343         // batch debugging code
9344         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9345         {
9346                 int i;
9347                 int j;
9348                 int c;
9349                 const int *e;
9350                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9351                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9352                 {
9353                         c = e[i];
9354                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9355                         {
9356                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9357                                 {
9358                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9359                                                 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);
9360                                         break;
9361                                 }
9362                         }
9363                 }
9364         }
9365 #endif
9366         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);
9367 }
9368
9369 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9370 {
9371         // pick the closest matching water plane
9372         int planeindex, vertexindex, bestplaneindex = -1;
9373         float d, bestd;
9374         vec3_t vert;
9375         const float *v;
9376         r_waterstate_waterplane_t *p;
9377         qboolean prepared = false;
9378         bestd = 0;
9379         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9380         {
9381                 if(p->camera_entity != rsurface.texture->camera_entity)
9382                         continue;
9383                 d = 0;
9384                 if(!prepared)
9385                 {
9386                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9387                         prepared = true;
9388                         if(rsurface.batchnumvertices == 0)
9389                                 break;
9390                 }
9391                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9392                 {
9393                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9394                         d += fabs(PlaneDiff(vert, &p->plane));
9395                 }
9396                 if (bestd > d || bestplaneindex < 0)
9397                 {
9398                         bestd = d;
9399                         bestplaneindex = planeindex;
9400                 }
9401         }
9402         return bestplaneindex;
9403         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9404         // this situation though, as it might be better to render single larger
9405         // batches with useless stuff (backface culled for example) than to
9406         // render multiple smaller batches
9407 }
9408
9409 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9410 {
9411         int i;
9412         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9413         rsurface.passcolor4f_vertexbuffer = 0;
9414         rsurface.passcolor4f_bufferoffset = 0;
9415         for (i = 0;i < rsurface.batchnumvertices;i++)
9416                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9417 }
9418
9419 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9420 {
9421         int i;
9422         float f;
9423         const float *v;
9424         const float *c;
9425         float *c2;
9426         if (rsurface.passcolor4f)
9427         {
9428                 // generate color arrays
9429                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9430                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9431                 rsurface.passcolor4f_vertexbuffer = 0;
9432                 rsurface.passcolor4f_bufferoffset = 0;
9433                 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)
9434                 {
9435                         f = RSurf_FogVertex(v);
9436                         c2[0] = c[0] * f;
9437                         c2[1] = c[1] * f;
9438                         c2[2] = c[2] * f;
9439                         c2[3] = c[3];
9440                 }
9441         }
9442         else
9443         {
9444                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9445                 rsurface.passcolor4f_vertexbuffer = 0;
9446                 rsurface.passcolor4f_bufferoffset = 0;
9447                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9448                 {
9449                         f = RSurf_FogVertex(v);
9450                         c2[0] = f;
9451                         c2[1] = f;
9452                         c2[2] = f;
9453                         c2[3] = 1;
9454                 }
9455         }
9456 }
9457
9458 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9459 {
9460         int i;
9461         float f;
9462         const float *v;
9463         const float *c;
9464         float *c2;
9465         if (!rsurface.passcolor4f)
9466                 return;
9467         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9468         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9469         rsurface.passcolor4f_vertexbuffer = 0;
9470         rsurface.passcolor4f_bufferoffset = 0;
9471         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)
9472         {
9473                 f = RSurf_FogVertex(v);
9474                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9475                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9476                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9477                 c2[3] = c[3];
9478         }
9479 }
9480
9481 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9482 {
9483         int i;
9484         const float *c;
9485         float *c2;
9486         if (!rsurface.passcolor4f)
9487                 return;
9488         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9489         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9490         rsurface.passcolor4f_vertexbuffer = 0;
9491         rsurface.passcolor4f_bufferoffset = 0;
9492         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9493         {
9494                 c2[0] = c[0] * r;
9495                 c2[1] = c[1] * g;
9496                 c2[2] = c[2] * b;
9497                 c2[3] = c[3] * a;
9498         }
9499 }
9500
9501 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9502 {
9503         int i;
9504         const float *c;
9505         float *c2;
9506         if (!rsurface.passcolor4f)
9507                 return;
9508         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9509         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9510         rsurface.passcolor4f_vertexbuffer = 0;
9511         rsurface.passcolor4f_bufferoffset = 0;
9512         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9513         {
9514                 c2[0] = c[0] + r_refdef.scene.ambient;
9515                 c2[1] = c[1] + r_refdef.scene.ambient;
9516                 c2[2] = c[2] + r_refdef.scene.ambient;
9517                 c2[3] = c[3];
9518         }
9519 }
9520
9521 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9522 {
9523         // TODO: optimize
9524         rsurface.passcolor4f = NULL;
9525         rsurface.passcolor4f_vertexbuffer = 0;
9526         rsurface.passcolor4f_bufferoffset = 0;
9527         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9528         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9529         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9530         GL_Color(r, g, b, a);
9531         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9532         RSurf_DrawBatch();
9533 }
9534
9535 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9536 {
9537         // TODO: optimize applyfog && applycolor case
9538         // just apply fog if necessary, and tint the fog color array if necessary
9539         rsurface.passcolor4f = NULL;
9540         rsurface.passcolor4f_vertexbuffer = 0;
9541         rsurface.passcolor4f_bufferoffset = 0;
9542         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9543         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9544         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9545         GL_Color(r, g, b, a);
9546         RSurf_DrawBatch();
9547 }
9548
9549 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9550 {
9551         // TODO: optimize
9552         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9553         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9554         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
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         RSurf_DrawBatch();
9560 }
9561
9562 static void RSurf_DrawBatch_GL11_ClampColor(void)
9563 {
9564         int i;
9565         const float *c1;
9566         float *c2;
9567         if (!rsurface.passcolor4f)
9568                 return;
9569         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9570         {
9571                 c2[0] = bound(0.0f, c1[0], 1.0f);
9572                 c2[1] = bound(0.0f, c1[1], 1.0f);
9573                 c2[2] = bound(0.0f, c1[2], 1.0f);
9574                 c2[3] = bound(0.0f, c1[3], 1.0f);
9575         }
9576 }
9577
9578 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9579 {
9580         int i;
9581         float f;
9582         const float *v;
9583         const float *n;
9584         float *c;
9585         //vec3_t eyedir;
9586
9587         // fake shading
9588         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9589         rsurface.passcolor4f_vertexbuffer = 0;
9590         rsurface.passcolor4f_bufferoffset = 0;
9591         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)
9592         {
9593                 f = -DotProduct(r_refdef.view.forward, n);
9594                 f = max(0, f);
9595                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9596                 f *= r_refdef.lightmapintensity;
9597                 Vector4Set(c, f, f, f, 1);
9598         }
9599 }
9600
9601 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9602 {
9603         RSurf_DrawBatch_GL11_ApplyFakeLight();
9604         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9605         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9606         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9607         GL_Color(r, g, b, a);
9608         RSurf_DrawBatch();
9609 }
9610
9611 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9612 {
9613         int i;
9614         float f;
9615         float alpha;
9616         const float *v;
9617         const float *n;
9618         float *c;
9619         vec3_t ambientcolor;
9620         vec3_t diffusecolor;
9621         vec3_t lightdir;
9622         // TODO: optimize
9623         // model lighting
9624         VectorCopy(rsurface.modellight_lightdir, lightdir);
9625         f = 0.5f * r_refdef.lightmapintensity;
9626         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9627         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9628         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9629         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9630         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9631         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9632         alpha = *a;
9633         if (VectorLength2(diffusecolor) > 0)
9634         {
9635                 // q3-style directional shading
9636                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9637                 rsurface.passcolor4f_vertexbuffer = 0;
9638                 rsurface.passcolor4f_bufferoffset = 0;
9639                 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)
9640                 {
9641                         if ((f = DotProduct(n, lightdir)) > 0)
9642                                 VectorMA(ambientcolor, f, diffusecolor, c);
9643                         else
9644                                 VectorCopy(ambientcolor, c);
9645                         c[3] = alpha;
9646                 }
9647                 *r = 1;
9648                 *g = 1;
9649                 *b = 1;
9650                 *a = 1;
9651                 *applycolor = false;
9652         }
9653         else
9654         {
9655                 *r = ambientcolor[0];
9656                 *g = ambientcolor[1];
9657                 *b = ambientcolor[2];
9658                 rsurface.passcolor4f = NULL;
9659                 rsurface.passcolor4f_vertexbuffer = 0;
9660                 rsurface.passcolor4f_bufferoffset = 0;
9661         }
9662 }
9663
9664 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9665 {
9666         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9667         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9668         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9669         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9670         GL_Color(r, g, b, a);
9671         RSurf_DrawBatch();
9672 }
9673
9674 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9675 {
9676         int i;
9677         float f;
9678         const float *v;
9679         float *c;
9680
9681         // fake shading
9682         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9683         rsurface.passcolor4f_vertexbuffer = 0;
9684         rsurface.passcolor4f_bufferoffset = 0;
9685
9686         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9687         {
9688                 f = 1 - RSurf_FogVertex(v);
9689                 c[0] = r;
9690                 c[1] = g;
9691                 c[2] = b;
9692                 c[3] = f * a;
9693         }
9694 }
9695
9696 void RSurf_SetupDepthAndCulling(void)
9697 {
9698         // submodels are biased to avoid z-fighting with world surfaces that they
9699         // may be exactly overlapping (avoids z-fighting artifacts on certain
9700         // doors and things in Quake maps)
9701         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9702         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9703         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9704         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9705 }
9706
9707 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9708 {
9709         // transparent sky would be ridiculous
9710         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9711                 return;
9712         R_SetupShader_Generic_NoTexture(false, false);
9713         skyrenderlater = true;
9714         RSurf_SetupDepthAndCulling();
9715         GL_DepthMask(true);
9716         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9717         // skymasking on them, and Quake3 never did sky masking (unlike
9718         // software Quake and software Quake2), so disable the sky masking
9719         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9720         // and skymasking also looks very bad when noclipping outside the
9721         // level, so don't use it then either.
9722         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9723         {
9724                 R_Mesh_ResetTextureState();
9725                 if (skyrendermasked)
9726                 {
9727                         R_SetupShader_DepthOrShadow(false);
9728                         // depth-only (masking)
9729                         GL_ColorMask(0,0,0,0);
9730                         // just to make sure that braindead drivers don't draw
9731                         // anything despite that colormask...
9732                         GL_BlendFunc(GL_ZERO, GL_ONE);
9733                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9734                         if (rsurface.batchvertex3fbuffer)
9735                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9736                         else
9737                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9738                 }
9739                 else
9740                 {
9741                         R_SetupShader_Generic_NoTexture(false, false);
9742                         // fog sky
9743                         GL_BlendFunc(GL_ONE, GL_ZERO);
9744                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9745                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9746                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9747                 }
9748                 RSurf_DrawBatch();
9749                 if (skyrendermasked)
9750                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9751         }
9752         R_Mesh_ResetTextureState();
9753         GL_Color(1, 1, 1, 1);
9754 }
9755
9756 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9757 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9758 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9759 {
9760         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9761                 return;
9762         if (prepass)
9763         {
9764                 // render screenspace normalmap to texture
9765                 GL_DepthMask(true);
9766                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9767                 RSurf_DrawBatch();
9768         }
9769
9770         // bind lightmap texture
9771
9772         // water/refraction/reflection/camera surfaces have to be handled specially
9773         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9774         {
9775                 int start, end, startplaneindex;
9776                 for (start = 0;start < texturenumsurfaces;start = end)
9777                 {
9778                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9779                         if(startplaneindex < 0)
9780                         {
9781                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9782                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9783                                 end = start + 1;
9784                                 continue;
9785                         }
9786                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9787                                 ;
9788                         // now that we have a batch using the same planeindex, render it
9789                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9790                         {
9791                                 // render water or distortion background
9792                                 GL_DepthMask(true);
9793                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9794                                 RSurf_DrawBatch();
9795                                 // blend surface on top
9796                                 GL_DepthMask(false);
9797                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9798                                 RSurf_DrawBatch();
9799                         }
9800                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9801                         {
9802                                 // render surface with reflection texture as input
9803                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9804                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9805                                 RSurf_DrawBatch();
9806                         }
9807                 }
9808                 return;
9809         }
9810
9811         // render surface batch normally
9812         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9813         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);
9814         RSurf_DrawBatch();
9815 }
9816
9817 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9818 {
9819         // OpenGL 1.3 path - anything not completely ancient
9820         qboolean applycolor;
9821         qboolean applyfog;
9822         int layerindex;
9823         const texturelayer_t *layer;
9824         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);
9825         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9826
9827         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9828         {
9829                 vec4_t layercolor;
9830                 int layertexrgbscale;
9831                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9832                 {
9833                         if (layerindex == 0)
9834                                 GL_AlphaTest(true);
9835                         else
9836                         {
9837                                 GL_AlphaTest(false);
9838                                 GL_DepthFunc(GL_EQUAL);
9839                         }
9840                 }
9841                 GL_DepthMask(layer->depthmask && writedepth);
9842                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9843                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9844                 {
9845                         layertexrgbscale = 4;
9846                         VectorScale(layer->color, 0.25f, layercolor);
9847                 }
9848                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9849                 {
9850                         layertexrgbscale = 2;
9851                         VectorScale(layer->color, 0.5f, layercolor);
9852                 }
9853                 else
9854                 {
9855                         layertexrgbscale = 1;
9856                         VectorScale(layer->color, 1.0f, layercolor);
9857                 }
9858                 layercolor[3] = layer->color[3];
9859                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9860                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9861                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9862                 switch (layer->type)
9863                 {
9864                 case TEXTURELAYERTYPE_LITTEXTURE:
9865                         // single-pass lightmapped texture with 2x rgbscale
9866                         R_Mesh_TexBind(0, r_texture_white);
9867                         R_Mesh_TexMatrix(0, NULL);
9868                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9869                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9870                         R_Mesh_TexBind(1, layer->texture);
9871                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9872                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9873                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9874                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9875                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9876                         else if (FAKELIGHT_ENABLED)
9877                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9878                         else if (rsurface.uselightmaptexture)
9879                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9880                         else
9881                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9882                         break;
9883                 case TEXTURELAYERTYPE_TEXTURE:
9884                         // singletexture unlit texture with transparency support
9885                         R_Mesh_TexBind(0, layer->texture);
9886                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9887                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9888                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9889                         R_Mesh_TexBind(1, 0);
9890                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9891                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9892                         break;
9893                 case TEXTURELAYERTYPE_FOG:
9894                         // singletexture fogging
9895                         if (layer->texture)
9896                         {
9897                                 R_Mesh_TexBind(0, layer->texture);
9898                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9899                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9900                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9901                         }
9902                         else
9903                         {
9904                                 R_Mesh_TexBind(0, 0);
9905                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9906                         }
9907                         R_Mesh_TexBind(1, 0);
9908                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9909                         // generate a color array for the fog pass
9910                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9911                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9912                         RSurf_DrawBatch();
9913                         break;
9914                 default:
9915                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9916                 }
9917         }
9918         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9919         {
9920                 GL_DepthFunc(GL_LEQUAL);
9921                 GL_AlphaTest(false);
9922         }
9923 }
9924
9925 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9926 {
9927         // OpenGL 1.1 - crusty old voodoo path
9928         qboolean applyfog;
9929         int layerindex;
9930         const texturelayer_t *layer;
9931         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);
9932         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9933
9934         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9935         {
9936                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9937                 {
9938                         if (layerindex == 0)
9939                                 GL_AlphaTest(true);
9940                         else
9941                         {
9942                                 GL_AlphaTest(false);
9943                                 GL_DepthFunc(GL_EQUAL);
9944                         }
9945                 }
9946                 GL_DepthMask(layer->depthmask && writedepth);
9947                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9948                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9949                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9950                 switch (layer->type)
9951                 {
9952                 case TEXTURELAYERTYPE_LITTEXTURE:
9953                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9954                         {
9955                                 // two-pass lit texture with 2x rgbscale
9956                                 // first the lightmap pass
9957                                 R_Mesh_TexBind(0, r_texture_white);
9958                                 R_Mesh_TexMatrix(0, NULL);
9959                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9960                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9961                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9962                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9963                                 else if (FAKELIGHT_ENABLED)
9964                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9965                                 else if (rsurface.uselightmaptexture)
9966                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9967                                 else
9968                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9969                                 // then apply the texture to it
9970                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9971                                 R_Mesh_TexBind(0, layer->texture);
9972                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9973                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9974                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9975                                 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);
9976                         }
9977                         else
9978                         {
9979                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9980                                 R_Mesh_TexBind(0, layer->texture);
9981                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9982                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9983                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9984                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9985                                         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);
9986                                 else
9987                                         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);
9988                         }
9989                         break;
9990                 case TEXTURELAYERTYPE_TEXTURE:
9991                         // singletexture unlit texture with transparency support
9992                         R_Mesh_TexBind(0, layer->texture);
9993                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9994                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9995                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9996                         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);
9997                         break;
9998                 case TEXTURELAYERTYPE_FOG:
9999                         // singletexture fogging
10000                         if (layer->texture)
10001                         {
10002                                 R_Mesh_TexBind(0, layer->texture);
10003                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10004                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10005                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10006                         }
10007                         else
10008                         {
10009                                 R_Mesh_TexBind(0, 0);
10010                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10011                         }
10012                         // generate a color array for the fog pass
10013                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10014                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10015                         RSurf_DrawBatch();
10016                         break;
10017                 default:
10018                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10019                 }
10020         }
10021         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10022         {
10023                 GL_DepthFunc(GL_LEQUAL);
10024                 GL_AlphaTest(false);
10025         }
10026 }
10027
10028 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10029 {
10030         int vi;
10031         int j;
10032         r_vertexgeneric_t *batchvertex;
10033         float c[4];
10034
10035 //      R_Mesh_ResetTextureState();
10036         R_SetupShader_Generic_NoTexture(false, false);
10037
10038         if(rsurface.texture && rsurface.texture->currentskinframe)
10039         {
10040                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10041                 c[3] *= rsurface.texture->currentalpha;
10042         }
10043         else
10044         {
10045                 c[0] = 1;
10046                 c[1] = 0;
10047                 c[2] = 1;
10048                 c[3] = 1;
10049         }
10050
10051         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10052         {
10053                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10054                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10055                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10056         }
10057
10058         // brighten it up (as texture value 127 means "unlit")
10059         c[0] *= 2 * r_refdef.view.colorscale;
10060         c[1] *= 2 * r_refdef.view.colorscale;
10061         c[2] *= 2 * r_refdef.view.colorscale;
10062
10063         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10064                 c[3] *= r_wateralpha.value;
10065
10066         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10067         {
10068                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10069                 GL_DepthMask(false);
10070         }
10071         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10072         {
10073                 GL_BlendFunc(GL_ONE, GL_ONE);
10074                 GL_DepthMask(false);
10075         }
10076         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10077         {
10078                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10079                 GL_DepthMask(false);
10080         }
10081         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10082         {
10083                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10084                 GL_DepthMask(false);
10085         }
10086         else
10087         {
10088                 GL_BlendFunc(GL_ONE, GL_ZERO);
10089                 GL_DepthMask(writedepth);
10090         }
10091
10092         if (r_showsurfaces.integer == 3)
10093         {
10094                 rsurface.passcolor4f = NULL;
10095
10096                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10097                 {
10098                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10099
10100                         rsurface.passcolor4f = NULL;
10101                         rsurface.passcolor4f_vertexbuffer = 0;
10102                         rsurface.passcolor4f_bufferoffset = 0;
10103                 }
10104                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10105                 {
10106                         qboolean applycolor = true;
10107                         float one = 1.0;
10108
10109                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10110
10111                         r_refdef.lightmapintensity = 1;
10112                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10113                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10114                 }
10115                 else if (FAKELIGHT_ENABLED)
10116                 {
10117                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10118
10119                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10120                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10121                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10122                 }
10123                 else
10124                 {
10125                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10126
10127                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10128                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10129                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10130                 }
10131
10132                 if(!rsurface.passcolor4f)
10133                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10134
10135                 RSurf_DrawBatch_GL11_ApplyAmbient();
10136                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10137                 if(r_refdef.fogenabled)
10138                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10139                 RSurf_DrawBatch_GL11_ClampColor();
10140
10141                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10142                 R_SetupShader_Generic_NoTexture(false, false);
10143                 RSurf_DrawBatch();
10144         }
10145         else if (!r_refdef.view.showdebug)
10146         {
10147                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10148                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10149                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10150                 {
10151                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10152                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10153                 }
10154                 R_Mesh_PrepareVertices_Generic_Unlock();
10155                 RSurf_DrawBatch();
10156         }
10157         else if (r_showsurfaces.integer == 4)
10158         {
10159                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10160                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10161                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10162                 {
10163                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10164                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10165                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10166                 }
10167                 R_Mesh_PrepareVertices_Generic_Unlock();
10168                 RSurf_DrawBatch();
10169         }
10170         else if (r_showsurfaces.integer == 2)
10171         {
10172                 const int *e;
10173                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10174                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10175                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10176                 {
10177                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10178                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10179                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10180                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10181                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10182                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10183                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10184                 }
10185                 R_Mesh_PrepareVertices_Generic_Unlock();
10186                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10187         }
10188         else
10189         {
10190                 int texturesurfaceindex;
10191                 int k;
10192                 const msurface_t *surface;
10193                 float surfacecolor4f[4];
10194                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10195                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10196                 vi = 0;
10197                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10198                 {
10199                         surface = texturesurfacelist[texturesurfaceindex];
10200                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10201                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10202                         for (j = 0;j < surface->num_vertices;j++)
10203                         {
10204                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10205                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10206                                 vi++;
10207                         }
10208                 }
10209                 R_Mesh_PrepareVertices_Generic_Unlock();
10210                 RSurf_DrawBatch();
10211         }
10212 }
10213
10214 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10215 {
10216         CHECKGLERROR
10217         RSurf_SetupDepthAndCulling();
10218         if (r_showsurfaces.integer)
10219         {
10220                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10221                 return;
10222         }
10223         switch (vid.renderpath)
10224         {
10225         case RENDERPATH_GL20:
10226         case RENDERPATH_D3D9:
10227         case RENDERPATH_D3D10:
10228         case RENDERPATH_D3D11:
10229         case RENDERPATH_SOFT:
10230         case RENDERPATH_GLES2:
10231                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10232                 break;
10233         case RENDERPATH_GL13:
10234         case RENDERPATH_GLES1:
10235                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10236                 break;
10237         case RENDERPATH_GL11:
10238                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10239                 break;
10240         }
10241         CHECKGLERROR
10242 }
10243
10244 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10245 {
10246         CHECKGLERROR
10247         RSurf_SetupDepthAndCulling();
10248         if (r_showsurfaces.integer)
10249         {
10250                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10251                 return;
10252         }
10253         switch (vid.renderpath)
10254         {
10255         case RENDERPATH_GL20:
10256         case RENDERPATH_D3D9:
10257         case RENDERPATH_D3D10:
10258         case RENDERPATH_D3D11:
10259         case RENDERPATH_SOFT:
10260         case RENDERPATH_GLES2:
10261                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10262                 break;
10263         case RENDERPATH_GL13:
10264         case RENDERPATH_GLES1:
10265                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10266                 break;
10267         case RENDERPATH_GL11:
10268                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10269                 break;
10270         }
10271         CHECKGLERROR
10272 }
10273
10274 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10275 {
10276         int i, j;
10277         int texturenumsurfaces, endsurface;
10278         texture_t *texture;
10279         const msurface_t *surface;
10280         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10281
10282         // if the model is static it doesn't matter what value we give for
10283         // wantnormals and wanttangents, so this logic uses only rules applicable
10284         // to a model, knowing that they are meaningless otherwise
10285         if (ent == r_refdef.scene.worldentity)
10286                 RSurf_ActiveWorldEntity();
10287         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10288                 RSurf_ActiveModelEntity(ent, false, false, false);
10289         else
10290         {
10291                 switch (vid.renderpath)
10292                 {
10293                 case RENDERPATH_GL20:
10294                 case RENDERPATH_D3D9:
10295                 case RENDERPATH_D3D10:
10296                 case RENDERPATH_D3D11:
10297                 case RENDERPATH_SOFT:
10298                 case RENDERPATH_GLES2:
10299                         RSurf_ActiveModelEntity(ent, true, true, false);
10300                         break;
10301                 case RENDERPATH_GL11:
10302                 case RENDERPATH_GL13:
10303                 case RENDERPATH_GLES1:
10304                         RSurf_ActiveModelEntity(ent, true, false, false);
10305                         break;
10306                 }
10307         }
10308
10309         if (r_transparentdepthmasking.integer)
10310         {
10311                 qboolean setup = false;
10312                 for (i = 0;i < numsurfaces;i = j)
10313                 {
10314                         j = i + 1;
10315                         surface = rsurface.modelsurfaces + surfacelist[i];
10316                         texture = surface->texture;
10317                         rsurface.texture = R_GetCurrentTexture(texture);
10318                         rsurface.lightmaptexture = NULL;
10319                         rsurface.deluxemaptexture = NULL;
10320                         rsurface.uselightmaptexture = false;
10321                         // scan ahead until we find a different texture
10322                         endsurface = min(i + 1024, numsurfaces);
10323                         texturenumsurfaces = 0;
10324                         texturesurfacelist[texturenumsurfaces++] = surface;
10325                         for (;j < endsurface;j++)
10326                         {
10327                                 surface = rsurface.modelsurfaces + surfacelist[j];
10328                                 if (texture != surface->texture)
10329                                         break;
10330                                 texturesurfacelist[texturenumsurfaces++] = surface;
10331                         }
10332                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10333                                 continue;
10334                         // render the range of surfaces as depth
10335                         if (!setup)
10336                         {
10337                                 setup = true;
10338                                 GL_ColorMask(0,0,0,0);
10339                                 GL_Color(1,1,1,1);
10340                                 GL_DepthTest(true);
10341                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10342                                 GL_DepthMask(true);
10343 //                              R_Mesh_ResetTextureState();
10344                                 R_SetupShader_DepthOrShadow(false);
10345                         }
10346                         RSurf_SetupDepthAndCulling();
10347                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10348                         if (rsurface.batchvertex3fbuffer)
10349                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10350                         else
10351                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10352                         RSurf_DrawBatch();
10353                 }
10354                 if (setup)
10355                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10356         }
10357
10358         for (i = 0;i < numsurfaces;i = j)
10359         {
10360                 j = i + 1;
10361                 surface = rsurface.modelsurfaces + surfacelist[i];
10362                 texture = surface->texture;
10363                 rsurface.texture = R_GetCurrentTexture(texture);
10364                 // scan ahead until we find a different texture
10365                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10366                 texturenumsurfaces = 0;
10367                 texturesurfacelist[texturenumsurfaces++] = surface;
10368                 if(FAKELIGHT_ENABLED)
10369                 {
10370                         rsurface.lightmaptexture = NULL;
10371                         rsurface.deluxemaptexture = NULL;
10372                         rsurface.uselightmaptexture = false;
10373                         for (;j < endsurface;j++)
10374                         {
10375                                 surface = rsurface.modelsurfaces + surfacelist[j];
10376                                 if (texture != surface->texture)
10377                                         break;
10378                                 texturesurfacelist[texturenumsurfaces++] = surface;
10379                         }
10380                 }
10381                 else
10382                 {
10383                         rsurface.lightmaptexture = surface->lightmaptexture;
10384                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10385                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10386                         for (;j < endsurface;j++)
10387                         {
10388                                 surface = rsurface.modelsurfaces + surfacelist[j];
10389                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10390                                         break;
10391                                 texturesurfacelist[texturenumsurfaces++] = surface;
10392                         }
10393                 }
10394                 // render the range of surfaces
10395                 if (ent == r_refdef.scene.worldentity)
10396                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10397                 else
10398                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10399         }
10400         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10401 }
10402
10403 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10404 {
10405         // transparent surfaces get pushed off into the transparent queue
10406         int surfacelistindex;
10407         const msurface_t *surface;
10408         vec3_t tempcenter, center;
10409         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10410         {
10411                 surface = texturesurfacelist[surfacelistindex];
10412                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10413                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10414                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10415                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10416                 if (queueentity->transparent_offset) // transparent offset
10417                 {
10418                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10419                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10420                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10421                 }
10422                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10423         }
10424 }
10425
10426 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10427 {
10428         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10429                 return;
10430         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10431                 return;
10432         RSurf_SetupDepthAndCulling();
10433         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10434         if (rsurface.batchvertex3fbuffer)
10435                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10436         else
10437                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10438         RSurf_DrawBatch();
10439 }
10440
10441 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10442 {
10443         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10444         CHECKGLERROR
10445         if (depthonly)
10446                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10447         else if (prepass)
10448         {
10449                 if (!rsurface.texture->currentnumlayers)
10450                         return;
10451                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10452                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10453                 else
10454                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10455         }
10456         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10457                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10458         else if (!rsurface.texture->currentnumlayers)
10459                 return;
10460         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10461         {
10462                 // in the deferred case, transparent surfaces were queued during prepass
10463                 if (!r_shadow_usingdeferredprepass)
10464                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10465         }
10466         else
10467         {
10468                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10469                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10470         }
10471         CHECKGLERROR
10472 }
10473
10474 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10475 {
10476         int i, j;
10477         texture_t *texture;
10478         R_FrameData_SetMark();
10479         // break the surface list down into batches by texture and use of lightmapping
10480         for (i = 0;i < numsurfaces;i = j)
10481         {
10482                 j = i + 1;
10483                 // texture is the base texture pointer, rsurface.texture is the
10484                 // current frame/skin the texture is directing us to use (for example
10485                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10486                 // use skin 1 instead)
10487                 texture = surfacelist[i]->texture;
10488                 rsurface.texture = R_GetCurrentTexture(texture);
10489                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10490                 {
10491                         // if this texture is not the kind we want, skip ahead to the next one
10492                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10493                                 ;
10494                         continue;
10495                 }
10496                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10497                 {
10498                         rsurface.lightmaptexture = NULL;
10499                         rsurface.deluxemaptexture = NULL;
10500                         rsurface.uselightmaptexture = false;
10501                         // simply scan ahead until we find a different texture or lightmap state
10502                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10503                                 ;
10504                 }
10505                 else
10506                 {
10507                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10508                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10509                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10510                         // simply scan ahead until we find a different texture or lightmap state
10511                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10512                                 ;
10513                 }
10514                 // render the range of surfaces
10515                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10516         }
10517         R_FrameData_ReturnToMark();
10518 }
10519
10520 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10521 {
10522         CHECKGLERROR
10523         if (depthonly)
10524                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10525         else if (prepass)
10526         {
10527                 if (!rsurface.texture->currentnumlayers)
10528                         return;
10529                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10530                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10531                 else
10532                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10533         }
10534         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10535                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10536         else if (!rsurface.texture->currentnumlayers)
10537                 return;
10538         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10539         {
10540                 // in the deferred case, transparent surfaces were queued during prepass
10541                 if (!r_shadow_usingdeferredprepass)
10542                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10543         }
10544         else
10545         {
10546                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10547                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10548         }
10549         CHECKGLERROR
10550 }
10551
10552 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10553 {
10554         int i, j;
10555         texture_t *texture;
10556         R_FrameData_SetMark();
10557         // break the surface list down into batches by texture and use of lightmapping
10558         for (i = 0;i < numsurfaces;i = j)
10559         {
10560                 j = i + 1;
10561                 // texture is the base texture pointer, rsurface.texture is the
10562                 // current frame/skin the texture is directing us to use (for example
10563                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10564                 // use skin 1 instead)
10565                 texture = surfacelist[i]->texture;
10566                 rsurface.texture = R_GetCurrentTexture(texture);
10567                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10568                 {
10569                         // if this texture is not the kind we want, skip ahead to the next one
10570                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10571                                 ;
10572                         continue;
10573                 }
10574                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10575                 {
10576                         rsurface.lightmaptexture = NULL;
10577                         rsurface.deluxemaptexture = NULL;
10578                         rsurface.uselightmaptexture = false;
10579                         // simply scan ahead until we find a different texture or lightmap state
10580                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10581                                 ;
10582                 }
10583                 else
10584                 {
10585                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10586                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10587                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10588                         // simply scan ahead until we find a different texture or lightmap state
10589                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10590                                 ;
10591                 }
10592                 // render the range of surfaces
10593                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10594         }
10595         R_FrameData_ReturnToMark();
10596 }
10597
10598 float locboxvertex3f[6*4*3] =
10599 {
10600         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10601         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10602         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10603         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10604         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10605         1,0,0, 0,0,0, 0,1,0, 1,1,0
10606 };
10607
10608 unsigned short locboxelements[6*2*3] =
10609 {
10610          0, 1, 2, 0, 2, 3,
10611          4, 5, 6, 4, 6, 7,
10612          8, 9,10, 8,10,11,
10613         12,13,14, 12,14,15,
10614         16,17,18, 16,18,19,
10615         20,21,22, 20,22,23
10616 };
10617
10618 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10619 {
10620         int i, j;
10621         cl_locnode_t *loc = (cl_locnode_t *)ent;
10622         vec3_t mins, size;
10623         float vertex3f[6*4*3];
10624         CHECKGLERROR
10625         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10626         GL_DepthMask(false);
10627         GL_DepthRange(0, 1);
10628         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10629         GL_DepthTest(true);
10630         GL_CullFace(GL_NONE);
10631         R_EntityMatrix(&identitymatrix);
10632
10633 //      R_Mesh_ResetTextureState();
10634
10635         i = surfacelist[0];
10636         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10637                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10638                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10639                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10640
10641         if (VectorCompare(loc->mins, loc->maxs))
10642         {
10643                 VectorSet(size, 2, 2, 2);
10644                 VectorMA(loc->mins, -0.5f, size, mins);
10645         }
10646         else
10647         {
10648                 VectorCopy(loc->mins, mins);
10649                 VectorSubtract(loc->maxs, loc->mins, size);
10650         }
10651
10652         for (i = 0;i < 6*4*3;)
10653                 for (j = 0;j < 3;j++, i++)
10654                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10655
10656         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10657         R_SetupShader_Generic_NoTexture(false, false);
10658         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10659 }
10660
10661 void R_DrawLocs(void)
10662 {
10663         int index;
10664         cl_locnode_t *loc, *nearestloc;
10665         vec3_t center;
10666         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10667         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10668         {
10669                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10670                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10671         }
10672 }
10673
10674 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10675 {
10676         if (decalsystem->decals)
10677                 Mem_Free(decalsystem->decals);
10678         memset(decalsystem, 0, sizeof(*decalsystem));
10679 }
10680
10681 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)
10682 {
10683         tridecal_t *decal;
10684         tridecal_t *decals;
10685         int i;
10686
10687         // expand or initialize the system
10688         if (decalsystem->maxdecals <= decalsystem->numdecals)
10689         {
10690                 decalsystem_t old = *decalsystem;
10691                 qboolean useshortelements;
10692                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10693                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10694                 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)));
10695                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10696                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10697                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10698                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10699                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10700                 if (decalsystem->numdecals)
10701                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10702                 if (old.decals)
10703                         Mem_Free(old.decals);
10704                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10705                         decalsystem->element3i[i] = i;
10706                 if (useshortelements)
10707                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10708                                 decalsystem->element3s[i] = i;
10709         }
10710
10711         // grab a decal and search for another free slot for the next one
10712         decals = decalsystem->decals;
10713         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10714         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10715                 ;
10716         decalsystem->freedecal = i;
10717         if (decalsystem->numdecals <= i)
10718                 decalsystem->numdecals = i + 1;
10719
10720         // initialize the decal
10721         decal->lived = 0;
10722         decal->triangleindex = triangleindex;
10723         decal->surfaceindex = surfaceindex;
10724         decal->decalsequence = decalsequence;
10725         decal->color4f[0][0] = c0[0];
10726         decal->color4f[0][1] = c0[1];
10727         decal->color4f[0][2] = c0[2];
10728         decal->color4f[0][3] = 1;
10729         decal->color4f[1][0] = c1[0];
10730         decal->color4f[1][1] = c1[1];
10731         decal->color4f[1][2] = c1[2];
10732         decal->color4f[1][3] = 1;
10733         decal->color4f[2][0] = c2[0];
10734         decal->color4f[2][1] = c2[1];
10735         decal->color4f[2][2] = c2[2];
10736         decal->color4f[2][3] = 1;
10737         decal->vertex3f[0][0] = v0[0];
10738         decal->vertex3f[0][1] = v0[1];
10739         decal->vertex3f[0][2] = v0[2];
10740         decal->vertex3f[1][0] = v1[0];
10741         decal->vertex3f[1][1] = v1[1];
10742         decal->vertex3f[1][2] = v1[2];
10743         decal->vertex3f[2][0] = v2[0];
10744         decal->vertex3f[2][1] = v2[1];
10745         decal->vertex3f[2][2] = v2[2];
10746         decal->texcoord2f[0][0] = t0[0];
10747         decal->texcoord2f[0][1] = t0[1];
10748         decal->texcoord2f[1][0] = t1[0];
10749         decal->texcoord2f[1][1] = t1[1];
10750         decal->texcoord2f[2][0] = t2[0];
10751         decal->texcoord2f[2][1] = t2[1];
10752         TriangleNormal(v0, v1, v2, decal->plane);
10753         VectorNormalize(decal->plane);
10754         decal->plane[3] = DotProduct(v0, decal->plane);
10755 }
10756
10757 extern cvar_t cl_decals_bias;
10758 extern cvar_t cl_decals_models;
10759 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10760 // baseparms, parms, temps
10761 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)
10762 {
10763         int cornerindex;
10764         int index;
10765         float v[9][3];
10766         const float *vertex3f;
10767         const float *normal3f;
10768         int numpoints;
10769         float points[2][9][3];
10770         float temp[3];
10771         float tc[9][2];
10772         float f;
10773         float c[9][4];
10774         const int *e;
10775
10776         e = rsurface.modelelement3i + 3*triangleindex;
10777
10778         vertex3f = rsurface.modelvertex3f;
10779         normal3f = rsurface.modelnormal3f;
10780
10781         if (normal3f)
10782         {
10783                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10784                 {
10785                         index = 3*e[cornerindex];
10786                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10787                 }
10788         }
10789         else
10790         {
10791                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10792                 {
10793                         index = 3*e[cornerindex];
10794                         VectorCopy(vertex3f + index, v[cornerindex]);
10795                 }
10796         }
10797
10798         // cull backfaces
10799         //TriangleNormal(v[0], v[1], v[2], normal);
10800         //if (DotProduct(normal, localnormal) < 0.0f)
10801         //      continue;
10802         // clip by each of the box planes formed from the projection matrix
10803         // if anything survives, we emit the decal
10804         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]);
10805         if (numpoints < 3)
10806                 return;
10807         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]);
10808         if (numpoints < 3)
10809                 return;
10810         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]);
10811         if (numpoints < 3)
10812                 return;
10813         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]);
10814         if (numpoints < 3)
10815                 return;
10816         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]);
10817         if (numpoints < 3)
10818                 return;
10819         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]);
10820         if (numpoints < 3)
10821                 return;
10822         // some part of the triangle survived, so we have to accept it...
10823         if (dynamic)
10824         {
10825                 // dynamic always uses the original triangle
10826                 numpoints = 3;
10827                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10828                 {
10829                         index = 3*e[cornerindex];
10830                         VectorCopy(vertex3f + index, v[cornerindex]);
10831                 }
10832         }
10833         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10834         {
10835                 // convert vertex positions to texcoords
10836                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10837                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10838                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10839                 // calculate distance fade from the projection origin
10840                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10841                 f = bound(0.0f, f, 1.0f);
10842                 c[cornerindex][0] = r * f;
10843                 c[cornerindex][1] = g * f;
10844                 c[cornerindex][2] = b * f;
10845                 c[cornerindex][3] = 1.0f;
10846                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10847         }
10848         if (dynamic)
10849                 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);
10850         else
10851                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10852                         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);
10853 }
10854 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)
10855 {
10856         matrix4x4_t projection;
10857         decalsystem_t *decalsystem;
10858         qboolean dynamic;
10859         dp_model_t *model;
10860         const msurface_t *surface;
10861         const msurface_t *surfaces;
10862         const int *surfacelist;
10863         const texture_t *texture;
10864         int numtriangles;
10865         int numsurfacelist;
10866         int surfacelistindex;
10867         int surfaceindex;
10868         int triangleindex;
10869         float localorigin[3];
10870         float localnormal[3];
10871         float localmins[3];
10872         float localmaxs[3];
10873         float localsize;
10874         //float normal[3];
10875         float planes[6][4];
10876         float angles[3];
10877         bih_t *bih;
10878         int bih_triangles_count;
10879         int bih_triangles[256];
10880         int bih_surfaces[256];
10881
10882         decalsystem = &ent->decalsystem;
10883         model = ent->model;
10884         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10885         {
10886                 R_DecalSystem_Reset(&ent->decalsystem);
10887                 return;
10888         }
10889
10890         if (!model->brush.data_leafs && !cl_decals_models.integer)
10891         {
10892                 if (decalsystem->model)
10893                         R_DecalSystem_Reset(decalsystem);
10894                 return;
10895         }
10896
10897         if (decalsystem->model != model)
10898                 R_DecalSystem_Reset(decalsystem);
10899         decalsystem->model = model;
10900
10901         RSurf_ActiveModelEntity(ent, true, false, false);
10902
10903         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10904         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10905         VectorNormalize(localnormal);
10906         localsize = worldsize*rsurface.inversematrixscale;
10907         localmins[0] = localorigin[0] - localsize;
10908         localmins[1] = localorigin[1] - localsize;
10909         localmins[2] = localorigin[2] - localsize;
10910         localmaxs[0] = localorigin[0] + localsize;
10911         localmaxs[1] = localorigin[1] + localsize;
10912         localmaxs[2] = localorigin[2] + localsize;
10913
10914         //VectorCopy(localnormal, planes[4]);
10915         //VectorVectors(planes[4], planes[2], planes[0]);
10916         AnglesFromVectors(angles, localnormal, NULL, false);
10917         AngleVectors(angles, planes[0], planes[2], planes[4]);
10918         VectorNegate(planes[0], planes[1]);
10919         VectorNegate(planes[2], planes[3]);
10920         VectorNegate(planes[4], planes[5]);
10921         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10922         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10923         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10924         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10925         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10926         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10927
10928 #if 1
10929 // works
10930 {
10931         matrix4x4_t forwardprojection;
10932         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10933         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10934 }
10935 #else
10936 // broken
10937 {
10938         float projectionvector[4][3];
10939         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10940         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10941         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10942         projectionvector[0][0] = planes[0][0] * ilocalsize;
10943         projectionvector[0][1] = planes[1][0] * ilocalsize;
10944         projectionvector[0][2] = planes[2][0] * ilocalsize;
10945         projectionvector[1][0] = planes[0][1] * ilocalsize;
10946         projectionvector[1][1] = planes[1][1] * ilocalsize;
10947         projectionvector[1][2] = planes[2][1] * ilocalsize;
10948         projectionvector[2][0] = planes[0][2] * ilocalsize;
10949         projectionvector[2][1] = planes[1][2] * ilocalsize;
10950         projectionvector[2][2] = planes[2][2] * ilocalsize;
10951         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10952         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10953         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10954         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10955 }
10956 #endif
10957
10958         dynamic = model->surfmesh.isanimated;
10959         numsurfacelist = model->nummodelsurfaces;
10960         surfacelist = model->sortedmodelsurfaces;
10961         surfaces = model->data_surfaces;
10962
10963         bih = NULL;
10964         bih_triangles_count = -1;
10965         if(!dynamic)
10966         {
10967                 if(model->render_bih.numleafs)
10968                         bih = &model->render_bih;
10969                 else if(model->collision_bih.numleafs)
10970                         bih = &model->collision_bih;
10971         }
10972         if(bih)
10973                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10974         if(bih_triangles_count == 0)
10975                 return;
10976         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10977                 return;
10978         if(bih_triangles_count > 0)
10979         {
10980                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10981                 {
10982                         surfaceindex = bih_surfaces[triangleindex];
10983                         surface = surfaces + surfaceindex;
10984                         texture = surface->texture;
10985                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10986                                 continue;
10987                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10988                                 continue;
10989                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10990                 }
10991         }
10992         else
10993         {
10994                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10995                 {
10996                         surfaceindex = surfacelist[surfacelistindex];
10997                         surface = surfaces + surfaceindex;
10998                         // check cull box first because it rejects more than any other check
10999                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11000                                 continue;
11001                         // skip transparent surfaces
11002                         texture = surface->texture;
11003                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11004                                 continue;
11005                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11006                                 continue;
11007                         numtriangles = surface->num_triangles;
11008                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11009                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11010                 }
11011         }
11012 }
11013
11014 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11015 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)
11016 {
11017         int renderentityindex;
11018         float worldmins[3];
11019         float worldmaxs[3];
11020         entity_render_t *ent;
11021
11022         if (!cl_decals_newsystem.integer)
11023                 return;
11024
11025         worldmins[0] = worldorigin[0] - worldsize;
11026         worldmins[1] = worldorigin[1] - worldsize;
11027         worldmins[2] = worldorigin[2] - worldsize;
11028         worldmaxs[0] = worldorigin[0] + worldsize;
11029         worldmaxs[1] = worldorigin[1] + worldsize;
11030         worldmaxs[2] = worldorigin[2] + worldsize;
11031
11032         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11033
11034         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11035         {
11036                 ent = r_refdef.scene.entities[renderentityindex];
11037                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11038                         continue;
11039
11040                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11041         }
11042 }
11043
11044 typedef struct r_decalsystem_splatqueue_s
11045 {
11046         vec3_t worldorigin;
11047         vec3_t worldnormal;
11048         float color[4];
11049         float tcrange[4];
11050         float worldsize;
11051         int decalsequence;
11052 }
11053 r_decalsystem_splatqueue_t;
11054
11055 int r_decalsystem_numqueued = 0;
11056 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11057
11058 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)
11059 {
11060         r_decalsystem_splatqueue_t *queue;
11061
11062         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11063                 return;
11064
11065         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11066         VectorCopy(worldorigin, queue->worldorigin);
11067         VectorCopy(worldnormal, queue->worldnormal);
11068         Vector4Set(queue->color, r, g, b, a);
11069         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11070         queue->worldsize = worldsize;
11071         queue->decalsequence = cl.decalsequence++;
11072 }
11073
11074 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11075 {
11076         int i;
11077         r_decalsystem_splatqueue_t *queue;
11078
11079         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11080                 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);
11081         r_decalsystem_numqueued = 0;
11082 }
11083
11084 extern cvar_t cl_decals_max;
11085 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11086 {
11087         int i;
11088         decalsystem_t *decalsystem = &ent->decalsystem;
11089         int numdecals;
11090         int killsequence;
11091         tridecal_t *decal;
11092         float frametime;
11093         float lifetime;
11094
11095         if (!decalsystem->numdecals)
11096                 return;
11097
11098         if (r_showsurfaces.integer)
11099                 return;
11100
11101         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11102         {
11103                 R_DecalSystem_Reset(decalsystem);
11104                 return;
11105         }
11106
11107         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11108         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11109
11110         if (decalsystem->lastupdatetime)
11111                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11112         else
11113                 frametime = 0;
11114         decalsystem->lastupdatetime = r_refdef.scene.time;
11115         decal = decalsystem->decals;
11116         numdecals = decalsystem->numdecals;
11117
11118         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11119         {
11120                 if (decal->color4f[0][3])
11121                 {
11122                         decal->lived += frametime;
11123                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11124                         {
11125                                 memset(decal, 0, sizeof(*decal));
11126                                 if (decalsystem->freedecal > i)
11127                                         decalsystem->freedecal = i;
11128                         }
11129                 }
11130         }
11131         decal = decalsystem->decals;
11132         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11133                 numdecals--;
11134
11135         // collapse the array by shuffling the tail decals into the gaps
11136         for (;;)
11137         {
11138                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11139                         decalsystem->freedecal++;
11140                 if (decalsystem->freedecal == numdecals)
11141                         break;
11142                 decal[decalsystem->freedecal] = decal[--numdecals];
11143         }
11144
11145         decalsystem->numdecals = numdecals;
11146
11147         if (numdecals <= 0)
11148         {
11149                 // if there are no decals left, reset decalsystem
11150                 R_DecalSystem_Reset(decalsystem);
11151         }
11152 }
11153
11154 extern skinframe_t *decalskinframe;
11155 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11156 {
11157         int i;
11158         decalsystem_t *decalsystem = &ent->decalsystem;
11159         int numdecals;
11160         tridecal_t *decal;
11161         float faderate;
11162         float alpha;
11163         float *v3f;
11164         float *c4f;
11165         float *t2f;
11166         const int *e;
11167         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11168         int numtris = 0;
11169
11170         numdecals = decalsystem->numdecals;
11171         if (!numdecals)
11172                 return;
11173
11174         if (r_showsurfaces.integer)
11175                 return;
11176
11177         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11178         {
11179                 R_DecalSystem_Reset(decalsystem);
11180                 return;
11181         }
11182
11183         // if the model is static it doesn't matter what value we give for
11184         // wantnormals and wanttangents, so this logic uses only rules applicable
11185         // to a model, knowing that they are meaningless otherwise
11186         if (ent == r_refdef.scene.worldentity)
11187                 RSurf_ActiveWorldEntity();
11188         else
11189                 RSurf_ActiveModelEntity(ent, false, false, false);
11190
11191         decalsystem->lastupdatetime = r_refdef.scene.time;
11192         decal = decalsystem->decals;
11193
11194         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11195
11196         // update vertex positions for animated models
11197         v3f = decalsystem->vertex3f;
11198         c4f = decalsystem->color4f;
11199         t2f = decalsystem->texcoord2f;
11200         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11201         {
11202                 if (!decal->color4f[0][3])
11203                         continue;
11204
11205                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11206                         continue;
11207
11208                 // skip backfaces
11209                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11210                         continue;
11211
11212                 // update color values for fading decals
11213                 if (decal->lived >= cl_decals_time.value)
11214                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11215                 else
11216                         alpha = 1.0f;
11217
11218                 c4f[ 0] = decal->color4f[0][0] * alpha;
11219                 c4f[ 1] = decal->color4f[0][1] * alpha;
11220                 c4f[ 2] = decal->color4f[0][2] * alpha;
11221                 c4f[ 3] = 1;
11222                 c4f[ 4] = decal->color4f[1][0] * alpha;
11223                 c4f[ 5] = decal->color4f[1][1] * alpha;
11224                 c4f[ 6] = decal->color4f[1][2] * alpha;
11225                 c4f[ 7] = 1;
11226                 c4f[ 8] = decal->color4f[2][0] * alpha;
11227                 c4f[ 9] = decal->color4f[2][1] * alpha;
11228                 c4f[10] = decal->color4f[2][2] * alpha;
11229                 c4f[11] = 1;
11230
11231                 t2f[0] = decal->texcoord2f[0][0];
11232                 t2f[1] = decal->texcoord2f[0][1];
11233                 t2f[2] = decal->texcoord2f[1][0];
11234                 t2f[3] = decal->texcoord2f[1][1];
11235                 t2f[4] = decal->texcoord2f[2][0];
11236                 t2f[5] = decal->texcoord2f[2][1];
11237
11238                 // update vertex positions for animated models
11239                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11240                 {
11241                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11242                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11243                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11244                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11245                 }
11246                 else
11247                 {
11248                         VectorCopy(decal->vertex3f[0], v3f);
11249                         VectorCopy(decal->vertex3f[1], v3f + 3);
11250                         VectorCopy(decal->vertex3f[2], v3f + 6);
11251                 }
11252
11253                 if (r_refdef.fogenabled)
11254                 {
11255                         alpha = RSurf_FogVertex(v3f);
11256                         VectorScale(c4f, alpha, c4f);
11257                         alpha = RSurf_FogVertex(v3f + 3);
11258                         VectorScale(c4f + 4, alpha, c4f + 4);
11259                         alpha = RSurf_FogVertex(v3f + 6);
11260                         VectorScale(c4f + 8, alpha, c4f + 8);
11261                 }
11262
11263                 v3f += 9;
11264                 c4f += 12;
11265                 t2f += 6;
11266                 numtris++;
11267         }
11268
11269         if (numtris > 0)
11270         {
11271                 r_refdef.stats.drawndecals += numtris;
11272
11273                 // now render the decals all at once
11274                 // (this assumes they all use one particle font texture!)
11275                 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);
11276 //              R_Mesh_ResetTextureState();
11277                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11278                 GL_DepthMask(false);
11279                 GL_DepthRange(0, 1);
11280                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11281                 GL_DepthTest(true);
11282                 GL_CullFace(GL_NONE);
11283                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11284                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11285                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11286         }
11287 }
11288
11289 static void R_DrawModelDecals(void)
11290 {
11291         int i, numdecals;
11292
11293         // fade faster when there are too many decals
11294         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11295         for (i = 0;i < r_refdef.scene.numentities;i++)
11296                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11297
11298         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11299         for (i = 0;i < r_refdef.scene.numentities;i++)
11300                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11301                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11302
11303         R_DecalSystem_ApplySplatEntitiesQueue();
11304
11305         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11306         for (i = 0;i < r_refdef.scene.numentities;i++)
11307                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11308
11309         r_refdef.stats.totaldecals += numdecals;
11310
11311         if (r_showsurfaces.integer)
11312                 return;
11313
11314         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11315
11316         for (i = 0;i < r_refdef.scene.numentities;i++)
11317         {
11318                 if (!r_refdef.viewcache.entityvisible[i])
11319                         continue;
11320                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11321                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11322         }
11323 }
11324
11325 extern cvar_t mod_collision_bih;
11326 static void R_DrawDebugModel(void)
11327 {
11328         entity_render_t *ent = rsurface.entity;
11329         int i, j, k, l, flagsmask;
11330         const msurface_t *surface;
11331         dp_model_t *model = ent->model;
11332         vec3_t v;
11333
11334         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11335                 return;
11336
11337         if (r_showoverdraw.value > 0)
11338         {
11339                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11340                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11341                 R_SetupShader_Generic_NoTexture(false, false);
11342                 GL_DepthTest(false);
11343                 GL_DepthMask(false);
11344                 GL_DepthRange(0, 1);
11345                 GL_BlendFunc(GL_ONE, GL_ONE);
11346                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11347                 {
11348                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11349                                 continue;
11350                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11351                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11352                         {
11353                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11354                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11355                                 if (!rsurface.texture->currentlayers->depthmask)
11356                                         GL_Color(c, 0, 0, 1.0f);
11357                                 else if (ent == r_refdef.scene.worldentity)
11358                                         GL_Color(c, c, c, 1.0f);
11359                                 else
11360                                         GL_Color(0, c, 0, 1.0f);
11361                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11362                                 RSurf_DrawBatch();
11363                         }
11364                 }
11365                 rsurface.texture = NULL;
11366         }
11367
11368         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11369
11370 //      R_Mesh_ResetTextureState();
11371         R_SetupShader_Generic_NoTexture(false, false);
11372         GL_DepthRange(0, 1);
11373         GL_DepthTest(!r_showdisabledepthtest.integer);
11374         GL_DepthMask(false);
11375         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11376
11377         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11378         {
11379                 int triangleindex;
11380                 int bihleafindex;
11381                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11382                 const q3mbrush_t *brush;
11383                 const bih_t *bih = &model->collision_bih;
11384                 const bih_leaf_t *bihleaf;
11385                 float vertex3f[3][3];
11386                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11387                 cullbox = false;
11388                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11389                 {
11390                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11391                                 continue;
11392                         switch (bihleaf->type)
11393                         {
11394                         case BIH_BRUSH:
11395                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11396                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11397                                 {
11398                                         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);
11399                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11400                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11401                                 }
11402                                 break;
11403                         case BIH_COLLISIONTRIANGLE:
11404                                 triangleindex = bihleaf->itemindex;
11405                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11406                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11407                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11408                                 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);
11409                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11410                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11411                                 break;
11412                         case BIH_RENDERTRIANGLE:
11413                                 triangleindex = bihleaf->itemindex;
11414                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11415                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11416                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11417                                 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);
11418                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11419                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11420                                 break;
11421                         }
11422                 }
11423         }
11424
11425         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11426
11427 #ifndef USE_GLES2
11428         if (r_showtris.integer && qglPolygonMode)
11429         {
11430                 if (r_showdisabledepthtest.integer)
11431                 {
11432                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11433                         GL_DepthMask(false);
11434                 }
11435                 else
11436                 {
11437                         GL_BlendFunc(GL_ONE, GL_ZERO);
11438                         GL_DepthMask(true);
11439                 }
11440                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11441                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11442                 {
11443                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11444                                 continue;
11445                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11446                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11447                         {
11448                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11449                                 if (!rsurface.texture->currentlayers->depthmask)
11450                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11451                                 else if (ent == r_refdef.scene.worldentity)
11452                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11453                                 else
11454                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11455                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11456                                 RSurf_DrawBatch();
11457                         }
11458                 }
11459                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11460                 rsurface.texture = NULL;
11461         }
11462
11463         if (r_shownormals.value != 0 && qglBegin)
11464         {
11465                 if (r_showdisabledepthtest.integer)
11466                 {
11467                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11468                         GL_DepthMask(false);
11469                 }
11470                 else
11471                 {
11472                         GL_BlendFunc(GL_ONE, GL_ZERO);
11473                         GL_DepthMask(true);
11474                 }
11475                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11476                 {
11477                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11478                                 continue;
11479                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11480                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11481                         {
11482                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11483                                 qglBegin(GL_LINES);
11484                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11485                                 {
11486                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11487                                         {
11488                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11489                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11490                                                 qglVertex3f(v[0], v[1], v[2]);
11491                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11492                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11493                                                 qglVertex3f(v[0], v[1], v[2]);
11494                                         }
11495                                 }
11496                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11497                                 {
11498                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11499                                         {
11500                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11501                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11502                                                 qglVertex3f(v[0], v[1], v[2]);
11503                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11504                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11505                                                 qglVertex3f(v[0], v[1], v[2]);
11506                                         }
11507                                 }
11508                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11509                                 {
11510                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11511                                         {
11512                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11513                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11514                                                 qglVertex3f(v[0], v[1], v[2]);
11515                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11516                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11517                                                 qglVertex3f(v[0], v[1], v[2]);
11518                                         }
11519                                 }
11520                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11521                                 {
11522                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11523                                         {
11524                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11525                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11526                                                 qglVertex3f(v[0], v[1], v[2]);
11527                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11528                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11529                                                 qglVertex3f(v[0], v[1], v[2]);
11530                                         }
11531                                 }
11532                                 qglEnd();
11533                                 CHECKGLERROR
11534                         }
11535                 }
11536                 rsurface.texture = NULL;
11537         }
11538 #endif
11539 }
11540
11541 int r_maxsurfacelist = 0;
11542 const msurface_t **r_surfacelist = NULL;
11543 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11544 {
11545         int i, j, endj, flagsmask;
11546         dp_model_t *model = r_refdef.scene.worldmodel;
11547         msurface_t *surfaces;
11548         unsigned char *update;
11549         int numsurfacelist = 0;
11550         if (model == NULL)
11551                 return;
11552
11553         if (r_maxsurfacelist < model->num_surfaces)
11554         {
11555                 r_maxsurfacelist = model->num_surfaces;
11556                 if (r_surfacelist)
11557                         Mem_Free((msurface_t**)r_surfacelist);
11558                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11559         }
11560
11561         RSurf_ActiveWorldEntity();
11562
11563         surfaces = model->data_surfaces;
11564         update = model->brushq1.lightmapupdateflags;
11565
11566         // update light styles on this submodel
11567         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11568         {
11569                 model_brush_lightstyleinfo_t *style;
11570                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11571                 {
11572                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11573                         {
11574                                 int *list = style->surfacelist;
11575                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11576                                 for (j = 0;j < style->numsurfaces;j++)
11577                                         update[list[j]] = true;
11578                         }
11579                 }
11580         }
11581
11582         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11583
11584         if (debug)
11585         {
11586                 R_DrawDebugModel();
11587                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11588                 return;
11589         }
11590
11591         rsurface.lightmaptexture = NULL;
11592         rsurface.deluxemaptexture = NULL;
11593         rsurface.uselightmaptexture = false;
11594         rsurface.texture = NULL;
11595         rsurface.rtlight = NULL;
11596         numsurfacelist = 0;
11597         // add visible surfaces to draw list
11598         for (i = 0;i < model->nummodelsurfaces;i++)
11599         {
11600                 j = model->sortedmodelsurfaces[i];
11601                 if (r_refdef.viewcache.world_surfacevisible[j])
11602                         r_surfacelist[numsurfacelist++] = surfaces + j;
11603         }
11604         // update lightmaps if needed
11605         if (model->brushq1.firstrender)
11606         {
11607                 model->brushq1.firstrender = false;
11608                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11609                         if (update[j])
11610                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11611         }
11612         else if (update)
11613         {
11614                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11615                         if (r_refdef.viewcache.world_surfacevisible[j])
11616                                 if (update[j])
11617                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11618         }
11619         // don't do anything if there were no surfaces
11620         if (!numsurfacelist)
11621         {
11622                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11623                 return;
11624         }
11625         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11626
11627         // add to stats if desired
11628         if (r_speeds.integer && !skysurfaces && !depthonly)
11629         {
11630                 r_refdef.stats.world_surfaces += numsurfacelist;
11631                 for (j = 0;j < numsurfacelist;j++)
11632                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11633         }
11634
11635         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11636 }
11637
11638 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11639 {
11640         int i, j, endj, flagsmask;
11641         dp_model_t *model = ent->model;
11642         msurface_t *surfaces;
11643         unsigned char *update;
11644         int numsurfacelist = 0;
11645         if (model == NULL)
11646                 return;
11647
11648         if (r_maxsurfacelist < model->num_surfaces)
11649         {
11650                 r_maxsurfacelist = model->num_surfaces;
11651                 if (r_surfacelist)
11652                         Mem_Free((msurface_t **)r_surfacelist);
11653                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11654         }
11655
11656         // if the model is static it doesn't matter what value we give for
11657         // wantnormals and wanttangents, so this logic uses only rules applicable
11658         // to a model, knowing that they are meaningless otherwise
11659         if (ent == r_refdef.scene.worldentity)
11660                 RSurf_ActiveWorldEntity();
11661         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11662                 RSurf_ActiveModelEntity(ent, false, false, false);
11663         else if (prepass)
11664                 RSurf_ActiveModelEntity(ent, true, true, true);
11665         else if (depthonly)
11666         {
11667                 switch (vid.renderpath)
11668                 {
11669                 case RENDERPATH_GL20:
11670                 case RENDERPATH_D3D9:
11671                 case RENDERPATH_D3D10:
11672                 case RENDERPATH_D3D11:
11673                 case RENDERPATH_SOFT:
11674                 case RENDERPATH_GLES2:
11675                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11676                         break;
11677                 case RENDERPATH_GL11:
11678                 case RENDERPATH_GL13:
11679                 case RENDERPATH_GLES1:
11680                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11681                         break;
11682                 }
11683         }
11684         else
11685         {
11686                 switch (vid.renderpath)
11687                 {
11688                 case RENDERPATH_GL20:
11689                 case RENDERPATH_D3D9:
11690                 case RENDERPATH_D3D10:
11691                 case RENDERPATH_D3D11:
11692                 case RENDERPATH_SOFT:
11693                 case RENDERPATH_GLES2:
11694                         RSurf_ActiveModelEntity(ent, true, true, false);
11695                         break;
11696                 case RENDERPATH_GL11:
11697                 case RENDERPATH_GL13:
11698                 case RENDERPATH_GLES1:
11699                         RSurf_ActiveModelEntity(ent, true, false, false);
11700                         break;
11701                 }
11702         }
11703
11704         surfaces = model->data_surfaces;
11705         update = model->brushq1.lightmapupdateflags;
11706
11707         // update light styles
11708         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11709         {
11710                 model_brush_lightstyleinfo_t *style;
11711                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11712                 {
11713                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11714                         {
11715                                 int *list = style->surfacelist;
11716                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11717                                 for (j = 0;j < style->numsurfaces;j++)
11718                                         update[list[j]] = true;
11719                         }
11720                 }
11721         }
11722
11723         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11724
11725         if (debug)
11726         {
11727                 R_DrawDebugModel();
11728                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11729                 return;
11730         }
11731
11732         rsurface.lightmaptexture = NULL;
11733         rsurface.deluxemaptexture = NULL;
11734         rsurface.uselightmaptexture = false;
11735         rsurface.texture = NULL;
11736         rsurface.rtlight = NULL;
11737         numsurfacelist = 0;
11738         // add visible surfaces to draw list
11739         for (i = 0;i < model->nummodelsurfaces;i++)
11740                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11741         // don't do anything if there were no surfaces
11742         if (!numsurfacelist)
11743         {
11744                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11745                 return;
11746         }
11747         // update lightmaps if needed
11748         if (update)
11749         {
11750                 int updated = 0;
11751                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11752                 {
11753                         if (update[j])
11754                         {
11755                                 updated++;
11756                                 R_BuildLightMap(ent, surfaces + j);
11757                         }
11758                 }
11759         }
11760         if (update)
11761                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11762                         if (update[j])
11763                                 R_BuildLightMap(ent, surfaces + j);
11764         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11765
11766         // add to stats if desired
11767         if (r_speeds.integer && !skysurfaces && !depthonly)
11768         {
11769                 r_refdef.stats.entities_surfaces += numsurfacelist;
11770                 for (j = 0;j < numsurfacelist;j++)
11771                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11772         }
11773
11774         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11775 }
11776
11777 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11778 {
11779         static texture_t texture;
11780         static msurface_t surface;
11781         const msurface_t *surfacelist = &surface;
11782
11783         // fake enough texture and surface state to render this geometry
11784
11785         texture.update_lastrenderframe = -1; // regenerate this texture
11786         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11787         texture.currentskinframe = skinframe;
11788         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11789         texture.offsetmapping = OFFSETMAPPING_OFF;
11790         texture.offsetscale = 1;
11791         texture.specularscalemod = 1;
11792         texture.specularpowermod = 1;
11793
11794         surface.texture = &texture;
11795         surface.num_triangles = numtriangles;
11796         surface.num_firsttriangle = firsttriangle;
11797         surface.num_vertices = numvertices;
11798         surface.num_firstvertex = firstvertex;
11799
11800         // now render it
11801         rsurface.texture = R_GetCurrentTexture(surface.texture);
11802         rsurface.lightmaptexture = NULL;
11803         rsurface.deluxemaptexture = NULL;
11804         rsurface.uselightmaptexture = false;
11805         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11806 }
11807
11808 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)
11809 {
11810         static msurface_t surface;
11811         const msurface_t *surfacelist = &surface;
11812
11813         // fake enough texture and surface state to render this geometry
11814         surface.texture = texture;
11815         surface.num_triangles = numtriangles;
11816         surface.num_firsttriangle = firsttriangle;
11817         surface.num_vertices = numvertices;
11818         surface.num_firstvertex = firstvertex;
11819
11820         // now render it
11821         rsurface.texture = R_GetCurrentTexture(surface.texture);
11822         rsurface.lightmaptexture = NULL;
11823         rsurface.deluxemaptexture = NULL;
11824         rsurface.uselightmaptexture = false;
11825         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11826 }