]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
removed r_shadow_deferred_8bitrange cvar
[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 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 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 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         qboolean debugshader = gl_paranoid.integer != 0;
1457         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1458         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1459         if (!debugshader)
1460         {
1461                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1462                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1463         }
1464         if ((!vsbin && vertstring) || (!psbin && fragstring))
1465         {
1466                 const char* dllnames_d3dx9 [] =
1467                 {
1468                         "d3dx9_43.dll",
1469                         "d3dx9_42.dll",
1470                         "d3dx9_41.dll",
1471                         "d3dx9_40.dll",
1472                         "d3dx9_39.dll",
1473                         "d3dx9_38.dll",
1474                         "d3dx9_37.dll",
1475                         "d3dx9_36.dll",
1476                         "d3dx9_35.dll",
1477                         "d3dx9_34.dll",
1478                         "d3dx9_33.dll",
1479                         "d3dx9_32.dll",
1480                         "d3dx9_31.dll",
1481                         "d3dx9_30.dll",
1482                         "d3dx9_29.dll",
1483                         "d3dx9_28.dll",
1484                         "d3dx9_27.dll",
1485                         "d3dx9_26.dll",
1486                         "d3dx9_25.dll",
1487                         "d3dx9_24.dll",
1488                         NULL
1489                 };
1490                 dllhandle_t d3dx9_dll = NULL;
1491                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1492                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1493                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494                 dllfunction_t d3dx9_dllfuncs[] =
1495                 {
1496                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1497                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1498                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1499                         {NULL, NULL}
1500                 };
1501                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1502                 {
1503                         DWORD shaderflags = 0;
1504                         if (debugshader)
1505                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1506                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1507                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1508                         if (vertstring && vertstring[0])
1509                         {
1510                                 if (debugshader)
1511                                 {
1512 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1513 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1514                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1515                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1516                                 }
1517                                 else
1518                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1519                                 if (vsbuffer)
1520                                 {
1521                                         vsbinsize = vsbuffer->GetBufferSize();
1522                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1523                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1524                                         vsbuffer->Release();
1525                                 }
1526                                 if (vslog)
1527                                 {
1528                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1529                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1530                                         vslog->Release();
1531                                 }
1532                         }
1533                         if (fragstring && fragstring[0])
1534                         {
1535                                 if (debugshader)
1536                                 {
1537 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1538 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1539                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1540                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1541                                 }
1542                                 else
1543                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1544                                 if (psbuffer)
1545                                 {
1546                                         psbinsize = psbuffer->GetBufferSize();
1547                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1548                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1549                                         psbuffer->Release();
1550                                 }
1551                                 if (pslog)
1552                                 {
1553                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1554                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1555                                         pslog->Release();
1556                                 }
1557                         }
1558                         Sys_UnloadLibrary(&d3dx9_dll);
1559                 }
1560                 else
1561                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1562         }
1563         if (vsbin && psbin)
1564         {
1565                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1566                 if (FAILED(vsresult))
1567                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1568                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1569                 if (FAILED(psresult))
1570                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1571         }
1572         // free the shader data
1573         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1574         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1575 }
1576
1577 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1578 {
1579         int i;
1580         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1581         int vertstring_length = 0;
1582         int geomstring_length = 0;
1583         int fragstring_length = 0;
1584         char *t;
1585         char *vertexstring, *geometrystring, *fragmentstring;
1586         char *vertstring, *geomstring, *fragstring;
1587         char permutationname[256];
1588         char cachename[256];
1589         int vertstrings_count = 0;
1590         int geomstrings_count = 0;
1591         int fragstrings_count = 0;
1592         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1593         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1594         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595
1596         if (p->compiled)
1597                 return;
1598         p->compiled = true;
1599         p->vertexshader = NULL;
1600         p->pixelshader = NULL;
1601
1602         permutationname[0] = 0;
1603         cachename[0] = 0;
1604         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1605         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1606         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1607
1608         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1609         strlcat(cachename, "hlsl/", sizeof(cachename));
1610
1611         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1612         vertstrings_count = 0;
1613         geomstrings_count = 0;
1614         fragstrings_count = 0;
1615         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1616         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1617         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1618
1619         // the first pretext is which type of shader to compile as
1620         // (later these will all be bound together as a program object)
1621         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1622         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1623         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1624
1625         // the second pretext is the mode (for example a light source)
1626         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1627         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1628         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1629         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1630         strlcat(cachename, modeinfo->name, sizeof(cachename));
1631
1632         // now add all the permutation pretexts
1633         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1634         {
1635                 if (permutation & (1<<i))
1636                 {
1637                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1638                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1639                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1641                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1642                 }
1643                 else
1644                 {
1645                         // keep line numbers correct
1646                         vertstrings_list[vertstrings_count++] = "\n";
1647                         geomstrings_list[geomstrings_count++] = "\n";
1648                         fragstrings_list[fragstrings_count++] = "\n";
1649                 }
1650         }
1651
1652         // add static parms
1653         R_CompileShader_AddStaticParms(mode, permutation);
1654         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1655         vertstrings_count += shaderstaticparms_count;
1656         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         geomstrings_count += shaderstaticparms_count;
1658         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         fragstrings_count += shaderstaticparms_count;
1660
1661         // replace spaces in the cachename with _ characters
1662         for (i = 0;cachename[i];i++)
1663                 if (cachename[i] == ' ')
1664                         cachename[i] = '_';
1665
1666         // now append the shader text itself
1667         vertstrings_list[vertstrings_count++] = vertexstring;
1668         geomstrings_list[geomstrings_count++] = geometrystring;
1669         fragstrings_list[fragstrings_count++] = fragmentstring;
1670
1671         // if any sources were NULL, clear the respective list
1672         if (!vertexstring)
1673                 vertstrings_count = 0;
1674         if (!geometrystring)
1675                 geomstrings_count = 0;
1676         if (!fragmentstring)
1677                 fragstrings_count = 0;
1678
1679         vertstring_length = 0;
1680         for (i = 0;i < vertstrings_count;i++)
1681                 vertstring_length += strlen(vertstrings_list[i]);
1682         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1683         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1684                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1685
1686         geomstring_length = 0;
1687         for (i = 0;i < geomstrings_count;i++)
1688                 geomstring_length += strlen(geomstrings_list[i]);
1689         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1690         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1691                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1692
1693         fragstring_length = 0;
1694         for (i = 0;i < fragstrings_count;i++)
1695                 fragstring_length += strlen(fragstrings_list[i]);
1696         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1697         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1698                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1699
1700         // try to load the cached shader, or generate one
1701         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1702
1703         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1704                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1705         else
1706                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1707
1708         // free the strings
1709         if (vertstring)
1710                 Mem_Free(vertstring);
1711         if (geomstring)
1712                 Mem_Free(geomstring);
1713         if (fragstring)
1714                 Mem_Free(fragstring);
1715         if (vertexstring)
1716                 Mem_Free(vertexstring);
1717         if (geometrystring)
1718                 Mem_Free(geometrystring);
1719         if (fragmentstring)
1720                 Mem_Free(fragmentstring);
1721 }
1722
1723 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1724 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1725 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);}
1726 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);}
1727 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);}
1728 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);}
1729
1730 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1731 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1732 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);}
1733 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);}
1734 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);}
1735 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);}
1736
1737 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1738 {
1739         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1740         if (r_hlsl_permutation != perm)
1741         {
1742                 r_hlsl_permutation = perm;
1743                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1744                 {
1745                         if (!r_hlsl_permutation->compiled)
1746                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1747                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1748                         {
1749                                 // remove features until we find a valid permutation
1750                                 int i;
1751                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1752                                 {
1753                                         // reduce i more quickly whenever it would not remove any bits
1754                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1755                                         if (!(permutation & j))
1756                                                 continue;
1757                                         permutation -= j;
1758                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1759                                         if (!r_hlsl_permutation->compiled)
1760                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1761                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1762                                                 break;
1763                                 }
1764                                 if (i >= SHADERPERMUTATION_COUNT)
1765                                 {
1766                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1767                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768                                         return; // no bit left to clear, entire mode is broken
1769                                 }
1770                         }
1771                 }
1772                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1773                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1774         }
1775         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1776         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1777         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1778 }
1779 #endif
1780
1781 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1782 {
1783         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1784         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1785         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1786         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1787 }
1788
1789 void R_GLSL_Restart_f(void)
1790 {
1791         unsigned int i, limit;
1792         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1793                 Mem_Free(glslshaderstring);
1794         glslshaderstring = NULL;
1795         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1796                 Mem_Free(hlslshaderstring);
1797         hlslshaderstring = NULL;
1798         switch(vid.renderpath)
1799         {
1800         case RENDERPATH_D3D9:
1801 #ifdef SUPPORTD3D
1802                 {
1803                         r_hlsl_permutation_t *p;
1804                         r_hlsl_permutation = NULL;
1805                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1806                         for (i = 0;i < limit;i++)
1807                         {
1808                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1809                                 {
1810                                         if (p->vertexshader)
1811                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1812                                         if (p->pixelshader)
1813                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1814                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1815                                 }
1816                         }
1817                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1818                 }
1819 #endif
1820                 break;
1821         case RENDERPATH_D3D10:
1822                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1823                 break;
1824         case RENDERPATH_D3D11:
1825                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826                 break;
1827         case RENDERPATH_GL20:
1828         case RENDERPATH_GLES2:
1829                 {
1830                         r_glsl_permutation_t *p;
1831                         r_glsl_permutation = NULL;
1832                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1833                         for (i = 0;i < limit;i++)
1834                         {
1835                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1836                                 {
1837                                         GL_Backend_FreeProgram(p->program);
1838                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1839                                 }
1840                         }
1841                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1842                 }
1843                 break;
1844         case RENDERPATH_GL11:
1845         case RENDERPATH_GL13:
1846         case RENDERPATH_GLES1:
1847                 break;
1848         case RENDERPATH_SOFT:
1849                 break;
1850         }
1851 }
1852
1853 void R_GLSL_DumpShader_f(void)
1854 {
1855         int i;
1856         qfile_t *file;
1857
1858         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1859         if (file)
1860         {
1861                 FS_Print(file, "/* The engine may define the following macros:\n");
1862                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1863                 for (i = 0;i < SHADERMODE_COUNT;i++)
1864                         FS_Print(file, glslshadermodeinfo[i].pretext);
1865                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1866                         FS_Print(file, shaderpermutationinfo[i].pretext);
1867                 FS_Print(file, "*/\n");
1868                 FS_Print(file, builtinshaderstring);
1869                 FS_Close(file);
1870                 Con_Printf("glsl/default.glsl written\n");
1871         }
1872         else
1873                 Con_Printf("failed to write to glsl/default.glsl\n");
1874
1875         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1876         if (file)
1877         {
1878                 FS_Print(file, "/* The engine may define the following macros:\n");
1879                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1880                 for (i = 0;i < SHADERMODE_COUNT;i++)
1881                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1882                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1883                         FS_Print(file, shaderpermutationinfo[i].pretext);
1884                 FS_Print(file, "*/\n");
1885                 FS_Print(file, builtinhlslshaderstring);
1886                 FS_Close(file);
1887                 Con_Printf("hlsl/default.hlsl written\n");
1888         }
1889         else
1890                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1891 }
1892
1893 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1894 {
1895         unsigned int permutation = 0;
1896         if (r_trippy.integer && !notrippy)
1897                 permutation |= SHADERPERMUTATION_TRIPPY;
1898         permutation |= SHADERPERMUTATION_VIEWTINT;
1899         if (first)
1900                 permutation |= SHADERPERMUTATION_DIFFUSE;
1901         if (second)
1902                 permutation |= SHADERPERMUTATION_SPECULAR;
1903         if (texturemode == GL_MODULATE)
1904                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1905         else if (texturemode == GL_ADD)
1906                 permutation |= SHADERPERMUTATION_GLOW;
1907         else if (texturemode == GL_DECAL)
1908                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1909         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1910                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1911         if (suppresstexalpha)
1912                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1913         if (!second)
1914                 texturemode = GL_MODULATE;
1915         if (vid.allowalphatocoverage)
1916                 GL_AlphaToCoverage(false);
1917         switch (vid.renderpath)
1918         {
1919         case RENDERPATH_D3D9:
1920 #ifdef SUPPORTD3D
1921                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1922                 R_Mesh_TexBind(GL20TU_FIRST , first );
1923                 R_Mesh_TexBind(GL20TU_SECOND, second);
1924                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1925                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1926 #endif
1927                 break;
1928         case RENDERPATH_D3D10:
1929                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930                 break;
1931         case RENDERPATH_D3D11:
1932                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1933                 break;
1934         case RENDERPATH_GL20:
1935         case RENDERPATH_GLES2:
1936                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1937                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1938                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1939                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1940                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1941                 break;
1942         case RENDERPATH_GL13:
1943         case RENDERPATH_GLES1:
1944                 R_Mesh_TexBind(0, first );
1945                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1946                 R_Mesh_TexBind(1, second);
1947                 if (second)
1948                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1949                 break;
1950         case RENDERPATH_GL11:
1951                 R_Mesh_TexBind(0, first );
1952                 break;
1953         case RENDERPATH_SOFT:
1954                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1955                 R_Mesh_TexBind(GL20TU_FIRST , first );
1956                 R_Mesh_TexBind(GL20TU_SECOND, second);
1957                 break;
1958         }
1959 }
1960
1961 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1962 {
1963         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1964 }
1965
1966 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1967 {
1968         unsigned int permutation = 0;
1969         if (r_trippy.integer && !notrippy)
1970                 permutation |= SHADERPERMUTATION_TRIPPY;
1971         if (vid.allowalphatocoverage)
1972                 GL_AlphaToCoverage(false);
1973         switch (vid.renderpath)
1974         {
1975         case RENDERPATH_D3D9:
1976 #ifdef SUPPORTD3D
1977                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1978 #endif
1979                 break;
1980         case RENDERPATH_D3D10:
1981                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1982                 break;
1983         case RENDERPATH_D3D11:
1984                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1985                 break;
1986         case RENDERPATH_GL20:
1987         case RENDERPATH_GLES2:
1988                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1989                 break;
1990         case RENDERPATH_GL13:
1991         case RENDERPATH_GLES1:
1992                 R_Mesh_TexBind(0, 0);
1993                 R_Mesh_TexBind(1, 0);
1994                 break;
1995         case RENDERPATH_GL11:
1996                 R_Mesh_TexBind(0, 0);
1997                 break;
1998         case RENDERPATH_SOFT:
1999                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2000                 break;
2001         }
2002 }
2003
2004 void R_SetupShader_ShowDepth(qboolean notrippy)
2005 {
2006         int permutation = 0;
2007         if (r_trippy.integer && !notrippy)
2008                 permutation |= SHADERPERMUTATION_TRIPPY;
2009         if (vid.allowalphatocoverage)
2010                 GL_AlphaToCoverage(false);
2011         switch (vid.renderpath)
2012         {
2013         case RENDERPATH_D3D9:
2014 #ifdef SUPPORTHLSL
2015                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2016 #endif
2017                 break;
2018         case RENDERPATH_D3D10:
2019                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2020                 break;
2021         case RENDERPATH_D3D11:
2022                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2023                 break;
2024         case RENDERPATH_GL20:
2025         case RENDERPATH_GLES2:
2026                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2027                 break;
2028         case RENDERPATH_GL13:
2029         case RENDERPATH_GLES1:
2030                 break;
2031         case RENDERPATH_GL11:
2032                 break;
2033         case RENDERPATH_SOFT:
2034                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2035                 break;
2036         }
2037 }
2038
2039 extern qboolean r_shadow_usingdeferredprepass;
2040 extern rtexture_t *r_shadow_attenuationgradienttexture;
2041 extern rtexture_t *r_shadow_attenuation2dtexture;
2042 extern rtexture_t *r_shadow_attenuation3dtexture;
2043 extern qboolean r_shadow_usingshadowmap2d;
2044 extern qboolean r_shadow_usingshadowmaportho;
2045 extern float r_shadow_shadowmap_texturescale[2];
2046 extern float r_shadow_shadowmap_parameters[4];
2047 extern qboolean r_shadow_shadowmapvsdct;
2048 extern qboolean r_shadow_shadowmapsampler;
2049 extern int r_shadow_shadowmappcf;
2050 extern rtexture_t *r_shadow_shadowmap2dtexture;
2051 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2052 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2053 extern matrix4x4_t r_shadow_shadowmapmatrix;
2054 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2055 extern int r_shadow_prepass_width;
2056 extern int r_shadow_prepass_height;
2057 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2058 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2059 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2060 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2061 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2062
2063 #define BLENDFUNC_ALLOWS_COLORMOD      1
2064 #define BLENDFUNC_ALLOWS_FOG           2
2065 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2066 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2067 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2068 static int R_BlendFuncFlags(int src, int dst)
2069 {
2070         int r = 0;
2071
2072         // a blendfunc allows colormod if:
2073         // a) it can never keep the destination pixel invariant, or
2074         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2075         // this is to prevent unintended side effects from colormod
2076
2077         // a blendfunc allows fog if:
2078         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2079         // this is to prevent unintended side effects from fog
2080
2081         // these checks are the output of fogeval.pl
2082
2083         r |= BLENDFUNC_ALLOWS_COLORMOD;
2084         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2085         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2086         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2093         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2094         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2098         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2099         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2100         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2101         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2102         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2103         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105
2106         return r;
2107 }
2108
2109 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)
2110 {
2111         // select a permutation of the lighting shader appropriate to this
2112         // combination of texture, entity, light source, and fogging, only use the
2113         // minimum features necessary to avoid wasting rendering time in the
2114         // fragment shader on features that are not being used
2115         unsigned int permutation = 0;
2116         unsigned int mode = 0;
2117         int blendfuncflags;
2118         static float dummy_colormod[3] = {1, 1, 1};
2119         float *colormod = rsurface.colormod;
2120         float m16f[16];
2121         matrix4x4_t tempmatrix;
2122         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2123         if (r_trippy.integer && !notrippy)
2124                 permutation |= SHADERPERMUTATION_TRIPPY;
2125         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2126                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2127         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2128                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2129         if (rsurfacepass == RSURFPASS_BACKGROUND)
2130         {
2131                 // distorted background
2132                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2133                 {
2134                         mode = SHADERMODE_WATER;
2135                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2136                         {
2137                                 // this is the right thing to do for wateralpha
2138                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2139                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2140                         }
2141                         else
2142                         {
2143                                 // this is the right thing to do for entity alpha
2144                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                         }
2147                 }
2148                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2149                 {
2150                         mode = SHADERMODE_REFRACTION;
2151                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2152                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153                 }
2154                 else
2155                 {
2156                         mode = SHADERMODE_GENERIC;
2157                         permutation |= SHADERPERMUTATION_DIFFUSE;
2158                         GL_BlendFunc(GL_ONE, GL_ZERO);
2159                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2160                 }
2161                 if (vid.allowalphatocoverage)
2162                         GL_AlphaToCoverage(false);
2163         }
2164         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2165         {
2166                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2167                 {
2168                         switch(rsurface.texture->offsetmapping)
2169                         {
2170                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2171                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2172                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2173                         case OFFSETMAPPING_OFF: break;
2174                         }
2175                 }
2176                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2177                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2178                 // normalmap (deferred prepass), may use alpha test on diffuse
2179                 mode = SHADERMODE_DEFERREDGEOMETRY;
2180                 GL_BlendFunc(GL_ONE, GL_ZERO);
2181                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2182                 if (vid.allowalphatocoverage)
2183                         GL_AlphaToCoverage(false);
2184         }
2185         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2186         {
2187                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2188                 {
2189                         switch(rsurface.texture->offsetmapping)
2190                         {
2191                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2192                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2193                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2194                         case OFFSETMAPPING_OFF: break;
2195                         }
2196                 }
2197                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2198                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2199                 // light source
2200                 mode = SHADERMODE_LIGHTSOURCE;
2201                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2202                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2203                 if (diffusescale > 0)
2204                         permutation |= SHADERPERMUTATION_DIFFUSE;
2205                 if (specularscale > 0)
2206                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2207                 if (r_refdef.fogenabled)
2208                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2209                 if (rsurface.texture->colormapping)
2210                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2211                 if (r_shadow_usingshadowmap2d)
2212                 {
2213                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2214                         if(r_shadow_shadowmapvsdct)
2215                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2216
2217                         if (r_shadow_shadowmapsampler)
2218                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2219                         if (r_shadow_shadowmappcf > 1)
2220                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2221                         else if (r_shadow_shadowmappcf)
2222                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2223                 }
2224                 if (rsurface.texture->reflectmasktexture)
2225                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2226                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2227                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2228                 if (vid.allowalphatocoverage)
2229                         GL_AlphaToCoverage(false);
2230         }
2231         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2232         {
2233                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2234                 {
2235                         switch(rsurface.texture->offsetmapping)
2236                         {
2237                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2238                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2239                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240                         case OFFSETMAPPING_OFF: break;
2241                         }
2242                 }
2243                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2244                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2245                 // unshaded geometry (fullbright or ambient model lighting)
2246                 mode = SHADERMODE_FLATCOLOR;
2247                 ambientscale = diffusescale = specularscale = 0;
2248                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2249                         permutation |= SHADERPERMUTATION_GLOW;
2250                 if (r_refdef.fogenabled)
2251                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2252                 if (rsurface.texture->colormapping)
2253                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2254                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2255                 {
2256                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2257                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2258
2259                         if (r_shadow_shadowmapsampler)
2260                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2261                         if (r_shadow_shadowmappcf > 1)
2262                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2263                         else if (r_shadow_shadowmappcf)
2264                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2265                 }
2266                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2267                         permutation |= SHADERPERMUTATION_REFLECTION;
2268                 if (rsurface.texture->reflectmasktexture)
2269                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2270                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2271                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2272                 // when using alphatocoverage, we don't need alphakill
2273                 if (vid.allowalphatocoverage)
2274                 {
2275                         if (r_transparent_alphatocoverage.integer)
2276                         {
2277                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2278                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2279                         }
2280                         else
2281                                 GL_AlphaToCoverage(false);
2282                 }
2283         }
2284         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2285         {
2286                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2287                 {
2288                         switch(rsurface.texture->offsetmapping)
2289                         {
2290                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2291                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2292                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2293                         case OFFSETMAPPING_OFF: break;
2294                         }
2295                 }
2296                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2297                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2298                 // directional model lighting
2299                 mode = SHADERMODE_LIGHTDIRECTION;
2300                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2301                         permutation |= SHADERPERMUTATION_GLOW;
2302                 permutation |= SHADERPERMUTATION_DIFFUSE;
2303                 if (specularscale > 0)
2304                         permutation |= SHADERPERMUTATION_SPECULAR;
2305                 if (r_refdef.fogenabled)
2306                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307                 if (rsurface.texture->colormapping)
2308                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2309                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2310                 {
2311                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2312                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313
2314                         if (r_shadow_shadowmapsampler)
2315                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2316                         if (r_shadow_shadowmappcf > 1)
2317                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2318                         else if (r_shadow_shadowmappcf)
2319                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2320                 }
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2322                         permutation |= SHADERPERMUTATION_REFLECTION;
2323                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2324                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2325                 if (rsurface.texture->reflectmasktexture)
2326                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2327                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2328                 {
2329                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2330                         if (r_shadow_bouncegriddirectional)
2331                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2332                 }
2333                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335                 // when using alphatocoverage, we don't need alphakill
2336                 if (vid.allowalphatocoverage)
2337                 {
2338                         if (r_transparent_alphatocoverage.integer)
2339                         {
2340                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2341                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2342                         }
2343                         else
2344                                 GL_AlphaToCoverage(false);
2345                 }
2346         }
2347         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2348         {
2349                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2350                 {
2351                         switch(rsurface.texture->offsetmapping)
2352                         {
2353                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2354                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2355                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2356                         case OFFSETMAPPING_OFF: break;
2357                         }
2358                 }
2359                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2360                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2361                 // ambient model lighting
2362                 mode = SHADERMODE_LIGHTDIRECTION;
2363                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2364                         permutation |= SHADERPERMUTATION_GLOW;
2365                 if (r_refdef.fogenabled)
2366                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2367                 if (rsurface.texture->colormapping)
2368                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2369                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2370                 {
2371                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2372                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2373
2374                         if (r_shadow_shadowmapsampler)
2375                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2376                         if (r_shadow_shadowmappcf > 1)
2377                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2378                         else if (r_shadow_shadowmappcf)
2379                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2380                 }
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2382                         permutation |= SHADERPERMUTATION_REFLECTION;
2383                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2384                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2385                 if (rsurface.texture->reflectmasktexture)
2386                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2387                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2388                 {
2389                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2390                         if (r_shadow_bouncegriddirectional)
2391                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2392                 }
2393                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2394                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2395                 // when using alphatocoverage, we don't need alphakill
2396                 if (vid.allowalphatocoverage)
2397                 {
2398                         if (r_transparent_alphatocoverage.integer)
2399                         {
2400                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2401                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2402                         }
2403                         else
2404                                 GL_AlphaToCoverage(false);
2405                 }
2406         }
2407         else
2408         {
2409                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2410                 {
2411                         switch(rsurface.texture->offsetmapping)
2412                         {
2413                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2414                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2415                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2416                         case OFFSETMAPPING_OFF: break;
2417                         }
2418                 }
2419                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2420                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2421                 // lightmapped wall
2422                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2423                         permutation |= SHADERPERMUTATION_GLOW;
2424                 if (r_refdef.fogenabled)
2425                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2426                 if (rsurface.texture->colormapping)
2427                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2428                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2429                 {
2430                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2431                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2432
2433                         if (r_shadow_shadowmapsampler)
2434                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2435                         if (r_shadow_shadowmappcf > 1)
2436                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2437                         else if (r_shadow_shadowmappcf)
2438                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2439                 }
2440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2441                         permutation |= SHADERPERMUTATION_REFLECTION;
2442                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2443                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2444                 if (rsurface.texture->reflectmasktexture)
2445                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2446                 if (FAKELIGHT_ENABLED)
2447                 {
2448                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2449                         mode = SHADERMODE_FAKELIGHT;
2450                         permutation |= SHADERPERMUTATION_DIFFUSE;
2451                         if (specularscale > 0)
2452                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2453                 }
2454                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2455                 {
2456                         // deluxemapping (light direction texture)
2457                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2458                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2459                         else
2460                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2461                         permutation |= SHADERPERMUTATION_DIFFUSE;
2462                         if (specularscale > 0)
2463                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2464                 }
2465                 else if (r_glsl_deluxemapping.integer >= 2)
2466                 {
2467                         // fake deluxemapping (uniform light direction in tangentspace)
2468                         if (rsurface.uselightmaptexture)
2469                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2470                         else
2471                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2472                         permutation |= SHADERPERMUTATION_DIFFUSE;
2473                         if (specularscale > 0)
2474                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2475                 }
2476                 else if (rsurface.uselightmaptexture)
2477                 {
2478                         // ordinary lightmapping (q1bsp, q3bsp)
2479                         mode = SHADERMODE_LIGHTMAP;
2480                 }
2481                 else
2482                 {
2483                         // ordinary vertex coloring (q3bsp)
2484                         mode = SHADERMODE_VERTEXCOLOR;
2485                 }
2486                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2487                 {
2488                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2489                         if (r_shadow_bouncegriddirectional)
2490                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2491                 }
2492                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2493                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494                 // when using alphatocoverage, we don't need alphakill
2495                 if (vid.allowalphatocoverage)
2496                 {
2497                         if (r_transparent_alphatocoverage.integer)
2498                         {
2499                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2500                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2501                         }
2502                         else
2503                                 GL_AlphaToCoverage(false);
2504                 }
2505         }
2506         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2507                 colormod = dummy_colormod;
2508         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2509                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2510         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2511                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2512         switch(vid.renderpath)
2513         {
2514         case RENDERPATH_D3D9:
2515 #ifdef SUPPORTD3D
2516                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2517                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2518                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2519                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2520                 if (mode == SHADERMODE_LIGHTSOURCE)
2521                 {
2522                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2523                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2524                 }
2525                 else
2526                 {
2527                         if (mode == SHADERMODE_LIGHTDIRECTION)
2528                         {
2529                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2530                         }
2531                 }
2532                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2533                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2534                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2535                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2536                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2537
2538                 if (mode == SHADERMODE_LIGHTSOURCE)
2539                 {
2540                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2541                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2542                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2545
2546                         // additive passes are only darkened by fog, not tinted
2547                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2548                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2549                 }
2550                 else
2551                 {
2552                         if (mode == SHADERMODE_FLATCOLOR)
2553                         {
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2555                         }
2556                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2557                         {
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2565                         }
2566                         else
2567                         {
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2573                         }
2574                         // additive passes are only darkened by fog, not tinted
2575                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2577                         else
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2579                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2580                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2584                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2585                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2587                         if (mode == SHADERMODE_WATER)
2588                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2589                 }
2590                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2591                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2592                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2593                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2594                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2595                 if (rsurface.texture->pantstexture)
2596                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2597                 else
2598                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2599                 if (rsurface.texture->shirttexture)
2600                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2601                 else
2602                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2603                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2604                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2605                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2607                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2608                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2609                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2610                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2611                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2612                         );
2613                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2614                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2615                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2616                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2617
2618                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2619                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2620                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2621                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2622                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2624                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2625                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2626                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2627                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2628                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2629                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2630                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2631                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2632                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2633                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2634                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2635                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2636                 {
2637                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2638                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2639                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2640                 }
2641                 else
2642                 {
2643                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2644                 }
2645 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2646 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2647                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2648                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2649                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2650                 {
2651                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2652                         if (rsurface.rtlight)
2653                         {
2654                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2655                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2656                         }
2657                 }
2658 #endif
2659                 break;
2660         case RENDERPATH_D3D10:
2661                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2662                 break;
2663         case RENDERPATH_D3D11:
2664                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2665                 break;
2666         case RENDERPATH_GL20:
2667         case RENDERPATH_GLES2:
2668                 if (!vid.useinterleavedarrays)
2669                 {
2670                         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);
2671                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2672                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2676                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2677                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2678                 }
2679                 else
2680                 {
2681                         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);
2682                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2683                 }
2684                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2685                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2686                 if (mode == SHADERMODE_LIGHTSOURCE)
2687                 {
2688                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2689                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2690                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2691                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2692                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2693                         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);
2694         
2695                         // additive passes are only darkened by fog, not tinted
2696                         if (r_glsl_permutation->loc_FogColor >= 0)
2697                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2698                         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);
2699                 }
2700                 else
2701                 {
2702                         if (mode == SHADERMODE_FLATCOLOR)
2703                         {
2704                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2705                         }
2706                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2707                         {
2708                                 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]);
2709                                 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]);
2710                                 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);
2711                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2712                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2713                                 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]);
2714                                 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]);
2715                         }
2716                         else
2717                         {
2718                                 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]);
2719                                 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]);
2720                                 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);
2721                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2722                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2723                         }
2724                         // additive passes are only darkened by fog, not tinted
2725                         if (r_glsl_permutation->loc_FogColor >= 0)
2726                         {
2727                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2728                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2729                                 else
2730                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2731                         }
2732                         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);
2733                         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]);
2734                         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]);
2735                         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]);
2736                         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]);
2737                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2738                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2739                         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);
2740                         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]);
2741                 }
2742                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2743                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2744                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2745                 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]);
2746                 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]);
2747
2748                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2749                 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));
2750                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2751                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2752                 {
2753                         if (rsurface.texture->pantstexture)
2754                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2755                         else
2756                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2757                 }
2758                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2759                 {
2760                         if (rsurface.texture->shirttexture)
2761                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2762                         else
2763                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2764                 }
2765                 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]);
2766                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2767                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2768                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2769                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2770                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2771                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2772                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2773                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2774                         );
2775                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2776                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2777                 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]);
2778                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2779                 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);}
2780                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2781
2782                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2783                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2784                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2785                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2786                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2787                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2788                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2789                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2790                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2791                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2792                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2793                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2794                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2795                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2796                 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);
2797                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2798                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2799                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2800                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2801                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2802                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2803                 {
2804                         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);
2805                         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);
2806                         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);
2807                 }
2808                 else
2809                 {
2810                         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);
2811                 }
2812                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2813                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2814                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2815                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2816                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2817                 {
2818                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2819                         if (rsurface.rtlight)
2820                         {
2821                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2822                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2823                         }
2824                 }
2825                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2826                 CHECKGLERROR
2827                 break;
2828         case RENDERPATH_GL11:
2829         case RENDERPATH_GL13:
2830         case RENDERPATH_GLES1:
2831                 break;
2832         case RENDERPATH_SOFT:
2833                 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);
2834                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2835                 R_SetupShader_SetPermutationSoft(mode, permutation);
2836                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2837                 if (mode == SHADERMODE_LIGHTSOURCE)
2838                 {
2839                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2840                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2845         
2846                         // additive passes are only darkened by fog, not tinted
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2848                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2849                 }
2850                 else
2851                 {
2852                         if (mode == SHADERMODE_FLATCOLOR)
2853                         {
2854                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2855                         }
2856                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2857                         {
2858                                 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]);
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2860                                 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);
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2863                                 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]);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2865                         }
2866                         else
2867                         {
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2870                                 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);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2873                         }
2874                         // additive passes are only darkened by fog, not tinted
2875                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2877                         else
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2879                         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);
2880                         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]);
2881                         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]);
2882                         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]);
2883                         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]);
2884                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2885                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2886                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2887                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2888                 }
2889                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2890                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2891                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2892                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2893                 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]);
2894
2895                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2896                 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));
2897                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2898                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2899                 {
2900                         if (rsurface.texture->pantstexture)
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2902                         else
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2904                 }
2905                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2906                 {
2907                         if (rsurface.texture->shirttexture)
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2909                         else
2910                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2911                 }
2912                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2913                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2916                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2917                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2918                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2919                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2920                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2921                         );
2922                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2923                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2924                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2925                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2926
2927                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2928                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2929                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2930                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2931                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2935                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2936                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2937                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2938                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2939                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2940                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2941                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2942                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2943                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2944                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2945                 {
2946                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2947                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2948                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2949                 }
2950                 else
2951                 {
2952                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2953                 }
2954 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2955 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2956                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2957                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2958                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2959                 {
2960                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2961                         if (rsurface.rtlight)
2962                         {
2963                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2964                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2965                         }
2966                 }
2967                 break;
2968         }
2969 }
2970
2971 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2972 {
2973         // select a permutation of the lighting shader appropriate to this
2974         // combination of texture, entity, light source, and fogging, only use the
2975         // minimum features necessary to avoid wasting rendering time in the
2976         // fragment shader on features that are not being used
2977         unsigned int permutation = 0;
2978         unsigned int mode = 0;
2979         const float *lightcolorbase = rtlight->currentcolor;
2980         float ambientscale = rtlight->ambientscale;
2981         float diffusescale = rtlight->diffusescale;
2982         float specularscale = rtlight->specularscale;
2983         // this is the location of the light in view space
2984         vec3_t viewlightorigin;
2985         // this transforms from view space (camera) to light space (cubemap)
2986         matrix4x4_t viewtolight;
2987         matrix4x4_t lighttoview;
2988         float viewtolight16f[16];
2989         // light source
2990         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2991         if (rtlight->currentcubemap != r_texture_whitecube)
2992                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2993         if (diffusescale > 0)
2994                 permutation |= SHADERPERMUTATION_DIFFUSE;
2995         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2996                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2997         if (r_shadow_usingshadowmap2d)
2998         {
2999                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3000                 if (r_shadow_shadowmapvsdct)
3001                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3002
3003                 if (r_shadow_shadowmapsampler)
3004                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3005                 if (r_shadow_shadowmappcf > 1)
3006                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3007                 else if (r_shadow_shadowmappcf)
3008                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3009         }
3010         if (vid.allowalphatocoverage)
3011                 GL_AlphaToCoverage(false);
3012         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3013         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3014         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3015         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3016         switch(vid.renderpath)
3017         {
3018         case RENDERPATH_D3D9:
3019 #ifdef SUPPORTD3D
3020                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3021                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3022                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3023                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3024                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3026                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3027                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3028                 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);
3029                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3030                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3031
3032                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3033                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3034                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3035                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3036                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3037                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3038 #endif
3039                 break;
3040         case RENDERPATH_D3D10:
3041                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3042                 break;
3043         case RENDERPATH_D3D11:
3044                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3045                 break;
3046         case RENDERPATH_GL20:
3047         case RENDERPATH_GLES2:
3048                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3049                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3050                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3051                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3052                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3053                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3054                 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]);
3055                 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]);
3056                 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);
3057                 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]);
3058                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3059
3060                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3061                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3062                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3063                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3064                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3065                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3066                 break;
3067         case RENDERPATH_GL11:
3068         case RENDERPATH_GL13:
3069         case RENDERPATH_GLES1:
3070                 break;
3071         case RENDERPATH_SOFT:
3072                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3073                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3074                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3075                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3076                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3077                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3078                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3079                 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]);
3080                 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);
3081                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3082                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3083
3084                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3085                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3086                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3087                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3088                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3089                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3090                 break;
3091         }
3092 }
3093
3094 #define SKINFRAME_HASH 1024
3095
3096 typedef struct
3097 {
3098         int loadsequence; // incremented each level change
3099         memexpandablearray_t array;
3100         skinframe_t *hash[SKINFRAME_HASH];
3101 }
3102 r_skinframe_t;
3103 r_skinframe_t r_skinframe;
3104
3105 void R_SkinFrame_PrepareForPurge(void)
3106 {
3107         r_skinframe.loadsequence++;
3108         // wrap it without hitting zero
3109         if (r_skinframe.loadsequence >= 200)
3110                 r_skinframe.loadsequence = 1;
3111 }
3112
3113 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3114 {
3115         if (!skinframe)
3116                 return;
3117         // mark the skinframe as used for the purging code
3118         skinframe->loadsequence = r_skinframe.loadsequence;
3119 }
3120
3121 void R_SkinFrame_Purge(void)
3122 {
3123         int i;
3124         skinframe_t *s;
3125         for (i = 0;i < SKINFRAME_HASH;i++)
3126         {
3127                 for (s = r_skinframe.hash[i];s;s = s->next)
3128                 {
3129                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3130                         {
3131                                 if (s->merged == s->base)
3132                                         s->merged = NULL;
3133                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3134                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3135                                 R_PurgeTexture(s->merged);s->merged = NULL;
3136                                 R_PurgeTexture(s->base  );s->base   = NULL;
3137                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3138                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3139                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3140                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3141                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3142                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3143                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3144                                 s->loadsequence = 0;
3145                         }
3146                 }
3147         }
3148 }
3149
3150 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3151         skinframe_t *item;
3152         char basename[MAX_QPATH];
3153
3154         Image_StripImageExtension(name, basename, sizeof(basename));
3155
3156         if( last == NULL ) {
3157                 int hashindex;
3158                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3159                 item = r_skinframe.hash[hashindex];
3160         } else {
3161                 item = last->next;
3162         }
3163
3164         // linearly search through the hash bucket
3165         for( ; item ; item = item->next ) {
3166                 if( !strcmp( item->basename, basename ) ) {
3167                         return item;
3168                 }
3169         }
3170         return NULL;
3171 }
3172
3173 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3174 {
3175         skinframe_t *item;
3176         int hashindex;
3177         char basename[MAX_QPATH];
3178
3179         Image_StripImageExtension(name, basename, sizeof(basename));
3180
3181         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3182         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3183                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3184                         break;
3185
3186         if (!item) {
3187                 rtexture_t *dyntexture;
3188                 // check whether its a dynamic texture
3189                 dyntexture = CL_GetDynTexture( basename );
3190                 if (!add && !dyntexture)
3191                         return NULL;
3192                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3193                 memset(item, 0, sizeof(*item));
3194                 strlcpy(item->basename, basename, sizeof(item->basename));
3195                 item->base = dyntexture; // either NULL or dyntexture handle
3196                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3197                 item->comparewidth = comparewidth;
3198                 item->compareheight = compareheight;
3199                 item->comparecrc = comparecrc;
3200                 item->next = r_skinframe.hash[hashindex];
3201                 r_skinframe.hash[hashindex] = item;
3202         }
3203         else if (textureflags & TEXF_FORCE_RELOAD)
3204         {
3205                 rtexture_t *dyntexture;
3206                 // check whether its a dynamic texture
3207                 dyntexture = CL_GetDynTexture( basename );
3208                 if (!add && !dyntexture)
3209                         return NULL;
3210                 if (item->merged == item->base)
3211                         item->merged = NULL;
3212                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3213                 R_PurgeTexture(item->stain );item->stain  = NULL;
3214                 R_PurgeTexture(item->merged);item->merged = NULL;
3215                 R_PurgeTexture(item->base  );item->base   = NULL;
3216                 R_PurgeTexture(item->pants );item->pants  = NULL;
3217                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3218                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3219                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3220                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3221                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3222         R_PurgeTexture(item->reflect);item->reflect = NULL;
3223                 item->loadsequence = 0;
3224         }
3225         else if( item->base == NULL )
3226         {
3227                 rtexture_t *dyntexture;
3228                 // check whether its a dynamic texture
3229                 // 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]
3230                 dyntexture = CL_GetDynTexture( basename );
3231                 item->base = dyntexture; // either NULL or dyntexture handle
3232         }
3233
3234         R_SkinFrame_MarkUsed(item);
3235         return item;
3236 }
3237
3238 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3239         { \
3240                 unsigned long long avgcolor[5], wsum; \
3241                 int pix, comp, w; \
3242                 avgcolor[0] = 0; \
3243                 avgcolor[1] = 0; \
3244                 avgcolor[2] = 0; \
3245                 avgcolor[3] = 0; \
3246                 avgcolor[4] = 0; \
3247                 wsum = 0; \
3248                 for(pix = 0; pix < cnt; ++pix) \
3249                 { \
3250                         w = 0; \
3251                         for(comp = 0; comp < 3; ++comp) \
3252                                 w += getpixel; \
3253                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3254                         { \
3255                                 ++wsum; \
3256                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3257                                 w = getpixel; \
3258                                 for(comp = 0; comp < 3; ++comp) \
3259                                         avgcolor[comp] += getpixel * w; \
3260                                 avgcolor[3] += w; \
3261                         } \
3262                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3263                         avgcolor[4] += getpixel; \
3264                 } \
3265                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3266                         avgcolor[3] = 1; \
3267                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3268                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3269                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3270                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3271         }
3272
3273 extern cvar_t gl_picmip;
3274 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3275 {
3276         int j;
3277         unsigned char *pixels;
3278         unsigned char *bumppixels;
3279         unsigned char *basepixels = NULL;
3280         int basepixels_width = 0;
3281         int basepixels_height = 0;
3282         skinframe_t *skinframe;
3283         rtexture_t *ddsbase = NULL;
3284         qboolean ddshasalpha = false;
3285         float ddsavgcolor[4];
3286         char basename[MAX_QPATH];
3287         int miplevel = R_PicmipForFlags(textureflags);
3288         int savemiplevel = miplevel;
3289         int mymiplevel;
3290
3291         if (cls.state == ca_dedicated)
3292                 return NULL;
3293
3294         // return an existing skinframe if already loaded
3295         // if loading of the first image fails, don't make a new skinframe as it
3296         // would cause all future lookups of this to be missing
3297         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3298         if (skinframe && skinframe->base)
3299                 return skinframe;
3300
3301         Image_StripImageExtension(name, basename, sizeof(basename));
3302
3303         // check for DDS texture file first
3304         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3305         {
3306                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3307                 if (basepixels == NULL)
3308                         return NULL;
3309         }
3310
3311         // FIXME handle miplevel
3312
3313         if (developer_loading.integer)
3314                 Con_Printf("loading skin \"%s\"\n", name);
3315
3316         // we've got some pixels to store, so really allocate this new texture now
3317         if (!skinframe)
3318                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3319         textureflags &= ~TEXF_FORCE_RELOAD;
3320         skinframe->stain = NULL;
3321         skinframe->merged = NULL;
3322         skinframe->base = NULL;
3323         skinframe->pants = NULL;
3324         skinframe->shirt = NULL;
3325         skinframe->nmap = NULL;
3326         skinframe->gloss = NULL;
3327         skinframe->glow = NULL;
3328         skinframe->fog = NULL;
3329         skinframe->reflect = NULL;
3330         skinframe->hasalpha = false;
3331
3332         if (ddsbase)
3333         {
3334                 skinframe->base = ddsbase;
3335                 skinframe->hasalpha = ddshasalpha;
3336                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3337                 if (r_loadfog && skinframe->hasalpha)
3338                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3339                 //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]);
3340         }
3341         else
3342         {
3343                 basepixels_width = image_width;
3344                 basepixels_height = image_height;
3345                 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);
3346                 if (textureflags & TEXF_ALPHA)
3347                 {
3348                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3349                         {
3350                                 if (basepixels[j] < 255)
3351                                 {
3352                                         skinframe->hasalpha = true;
3353                                         break;
3354                                 }
3355                         }
3356                         if (r_loadfog && skinframe->hasalpha)
3357                         {
3358                                 // has transparent pixels
3359                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3360                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3361                                 {
3362                                         pixels[j+0] = 255;
3363                                         pixels[j+1] = 255;
3364                                         pixels[j+2] = 255;
3365                                         pixels[j+3] = basepixels[j+3];
3366                                 }
3367                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3368                                 Mem_Free(pixels);
3369                         }
3370                 }
3371                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3372 #ifndef USE_GLES2
3373                 //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]);
3374                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3375                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3376                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3377                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3378 #endif
3379         }
3380
3381         if (r_loaddds)
3382         {
3383                 mymiplevel = savemiplevel;
3384                 if (r_loadnormalmap)
3385                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3386                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3387                 if (r_loadgloss)
3388                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3389                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3390                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3391                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3392         }
3393
3394         // _norm is the name used by tenebrae and has been adopted as standard
3395         if (r_loadnormalmap && skinframe->nmap == NULL)
3396         {
3397                 mymiplevel = savemiplevel;
3398                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3399                 {
3400                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3401                         Mem_Free(pixels);
3402                         pixels = NULL;
3403                 }
3404                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3405                 {
3406                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3407                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3408                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3409                         Mem_Free(pixels);
3410                         Mem_Free(bumppixels);
3411                 }
3412                 else if (r_shadow_bumpscale_basetexture.value > 0)
3413                 {
3414                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3415                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3416                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3417                         Mem_Free(pixels);
3418                 }
3419 #ifndef USE_GLES2
3420                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3421                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3422 #endif
3423         }
3424
3425         // _luma is supported only for tenebrae compatibility
3426         // _glow is the preferred name
3427         mymiplevel = savemiplevel;
3428         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3429         {
3430                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3431 #ifndef USE_GLES2
3432                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3433                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3434 #endif
3435                 Mem_Free(pixels);pixels = NULL;
3436         }
3437
3438         mymiplevel = savemiplevel;
3439         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3440         {
3441                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3442 #ifndef USE_GLES2
3443                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3444                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3445 #endif
3446                 Mem_Free(pixels);
3447                 pixels = NULL;
3448         }
3449
3450         mymiplevel = savemiplevel;
3451         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3452         {
3453                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3454 #ifndef USE_GLES2
3455                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3456                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3457 #endif
3458                 Mem_Free(pixels);
3459                 pixels = NULL;
3460         }
3461
3462         mymiplevel = savemiplevel;
3463         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3464         {
3465                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3466 #ifndef USE_GLES2
3467                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3468                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3469 #endif
3470                 Mem_Free(pixels);
3471                 pixels = NULL;
3472         }
3473
3474         mymiplevel = savemiplevel;
3475         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3476         {
3477                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3478 #ifndef USE_GLES2
3479                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3480                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3481 #endif
3482                 Mem_Free(pixels);
3483                 pixels = NULL;
3484         }
3485
3486         if (basepixels)
3487                 Mem_Free(basepixels);
3488
3489         return skinframe;
3490 }
3491
3492 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3493 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3494 {
3495         int i;
3496         unsigned char *temp1, *temp2;
3497         skinframe_t *skinframe;
3498
3499         if (cls.state == ca_dedicated)
3500                 return NULL;
3501
3502         // if already loaded just return it, otherwise make a new skinframe
3503         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3504         if (skinframe && skinframe->base)
3505                 return skinframe;
3506         textureflags &= ~TEXF_FORCE_RELOAD;
3507
3508         skinframe->stain = NULL;
3509         skinframe->merged = NULL;
3510         skinframe->base = NULL;
3511         skinframe->pants = NULL;
3512         skinframe->shirt = NULL;
3513         skinframe->nmap = NULL;
3514         skinframe->gloss = NULL;
3515         skinframe->glow = NULL;
3516         skinframe->fog = NULL;
3517         skinframe->reflect = NULL;
3518         skinframe->hasalpha = false;
3519
3520         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3521         if (!skindata)
3522                 return NULL;
3523
3524         if (developer_loading.integer)
3525                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3526
3527         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3528         {
3529                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3530                 temp2 = temp1 + width * height * 4;
3531                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3532                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3533                 Mem_Free(temp1);
3534         }
3535         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3536         if (textureflags & TEXF_ALPHA)
3537         {
3538                 for (i = 3;i < width * height * 4;i += 4)
3539                 {
3540                         if (skindata[i] < 255)
3541                         {
3542                                 skinframe->hasalpha = true;
3543                                 break;
3544                         }
3545                 }
3546                 if (r_loadfog && skinframe->hasalpha)
3547                 {
3548                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3549                         memcpy(fogpixels, skindata, width * height * 4);
3550                         for (i = 0;i < width * height * 4;i += 4)
3551                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3552                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3553                         Mem_Free(fogpixels);
3554                 }
3555         }
3556
3557         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3558         //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]);
3559
3560         return skinframe;
3561 }
3562
3563 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3564 {
3565         int i;
3566         int featuresmask;
3567         skinframe_t *skinframe;
3568
3569         if (cls.state == ca_dedicated)
3570                 return NULL;
3571
3572         // if already loaded just return it, otherwise make a new skinframe
3573         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3574         if (skinframe && skinframe->base)
3575                 return skinframe;
3576         textureflags &= ~TEXF_FORCE_RELOAD;
3577
3578         skinframe->stain = NULL;
3579         skinframe->merged = NULL;
3580         skinframe->base = NULL;
3581         skinframe->pants = NULL;
3582         skinframe->shirt = NULL;
3583         skinframe->nmap = NULL;
3584         skinframe->gloss = NULL;
3585         skinframe->glow = NULL;
3586         skinframe->fog = NULL;
3587         skinframe->reflect = NULL;
3588         skinframe->hasalpha = false;
3589
3590         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3591         if (!skindata)
3592                 return NULL;
3593
3594         if (developer_loading.integer)
3595                 Con_Printf("loading quake skin \"%s\"\n", name);
3596
3597         // 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)
3598         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3599         memcpy(skinframe->qpixels, skindata, width*height);
3600         skinframe->qwidth = width;
3601         skinframe->qheight = height;
3602
3603         featuresmask = 0;
3604         for (i = 0;i < width * height;i++)
3605                 featuresmask |= palette_featureflags[skindata[i]];
3606
3607         skinframe->hasalpha = false;
3608         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3609         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3610         skinframe->qgeneratemerged = true;
3611         skinframe->qgeneratebase = skinframe->qhascolormapping;
3612         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3613
3614         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3615         //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]);
3616
3617         return skinframe;
3618 }
3619
3620 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3621 {
3622         int width;
3623         int height;
3624         unsigned char *skindata;
3625
3626         if (!skinframe->qpixels)
3627                 return;
3628
3629         if (!skinframe->qhascolormapping)
3630                 colormapped = false;
3631
3632         if (colormapped)
3633         {
3634                 if (!skinframe->qgeneratebase)
3635                         return;
3636         }
3637         else
3638         {
3639                 if (!skinframe->qgeneratemerged)
3640                         return;
3641         }
3642
3643         width = skinframe->qwidth;
3644         height = skinframe->qheight;
3645         skindata = skinframe->qpixels;
3646
3647         if (skinframe->qgeneratenmap)
3648         {
3649                 unsigned char *temp1, *temp2;
3650                 skinframe->qgeneratenmap = false;
3651                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3652                 temp2 = temp1 + width * height * 4;
3653                 // use either a custom palette or the quake palette
3654                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3655                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3656                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3657                 Mem_Free(temp1);
3658         }
3659
3660         if (skinframe->qgenerateglow)
3661         {
3662                 skinframe->qgenerateglow = false;
3663                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3664         }
3665
3666         if (colormapped)
3667         {
3668                 skinframe->qgeneratebase = false;
3669                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3670                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3671                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3672         }
3673         else
3674         {
3675                 skinframe->qgeneratemerged = false;
3676                 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);
3677         }
3678
3679         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3680         {
3681                 Mem_Free(skinframe->qpixels);
3682                 skinframe->qpixels = NULL;
3683         }
3684 }
3685
3686 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)
3687 {
3688         int i;
3689         skinframe_t *skinframe;
3690
3691         if (cls.state == ca_dedicated)
3692                 return NULL;
3693
3694         // if already loaded just return it, otherwise make a new skinframe
3695         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3696         if (skinframe && skinframe->base)
3697                 return skinframe;
3698         textureflags &= ~TEXF_FORCE_RELOAD;
3699
3700         skinframe->stain = NULL;
3701         skinframe->merged = NULL;
3702         skinframe->base = NULL;
3703         skinframe->pants = NULL;
3704         skinframe->shirt = NULL;
3705         skinframe->nmap = NULL;
3706         skinframe->gloss = NULL;
3707         skinframe->glow = NULL;
3708         skinframe->fog = NULL;
3709         skinframe->reflect = NULL;
3710         skinframe->hasalpha = false;
3711
3712         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3713         if (!skindata)
3714                 return NULL;
3715
3716         if (developer_loading.integer)
3717                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3718
3719         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3720         if (textureflags & TEXF_ALPHA)
3721         {
3722                 for (i = 0;i < width * height;i++)
3723                 {
3724                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3725                         {
3726                                 skinframe->hasalpha = true;
3727                                 break;
3728                         }
3729                 }
3730                 if (r_loadfog && skinframe->hasalpha)
3731                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3732         }
3733
3734         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3735         //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]);
3736
3737         return skinframe;
3738 }
3739
3740 skinframe_t *R_SkinFrame_LoadMissing(void)
3741 {
3742         skinframe_t *skinframe;
3743
3744         if (cls.state == ca_dedicated)
3745                 return NULL;
3746
3747         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3748         skinframe->stain = NULL;
3749         skinframe->merged = NULL;
3750         skinframe->base = NULL;
3751         skinframe->pants = NULL;
3752         skinframe->shirt = NULL;
3753         skinframe->nmap = NULL;
3754         skinframe->gloss = NULL;
3755         skinframe->glow = NULL;
3756         skinframe->fog = NULL;
3757         skinframe->reflect = NULL;
3758         skinframe->hasalpha = false;
3759
3760         skinframe->avgcolor[0] = rand() / RAND_MAX;
3761         skinframe->avgcolor[1] = rand() / RAND_MAX;
3762         skinframe->avgcolor[2] = rand() / RAND_MAX;
3763         skinframe->avgcolor[3] = 1;
3764
3765         return skinframe;
3766 }
3767
3768 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3769 typedef struct suffixinfo_s
3770 {
3771         const char *suffix;
3772         qboolean flipx, flipy, flipdiagonal;
3773 }
3774 suffixinfo_t;
3775 static suffixinfo_t suffix[3][6] =
3776 {
3777         {
3778                 {"px",   false, false, false},
3779                 {"nx",   false, false, false},
3780                 {"py",   false, false, false},
3781                 {"ny",   false, false, false},
3782                 {"pz",   false, false, false},
3783                 {"nz",   false, false, false}
3784         },
3785         {
3786                 {"posx", false, false, false},
3787                 {"negx", false, false, false},
3788                 {"posy", false, false, false},
3789                 {"negy", false, false, false},
3790                 {"posz", false, false, false},
3791                 {"negz", false, false, false}
3792         },
3793         {
3794                 {"rt",    true, false,  true},
3795                 {"lf",   false,  true,  true},
3796                 {"ft",    true,  true, false},
3797                 {"bk",   false, false, false},
3798                 {"up",    true, false,  true},
3799                 {"dn",    true, false,  true}
3800         }
3801 };
3802
3803 static int componentorder[4] = {0, 1, 2, 3};
3804
3805 rtexture_t *R_LoadCubemap(const char *basename)
3806 {
3807         int i, j, cubemapsize;
3808         unsigned char *cubemappixels, *image_buffer;
3809         rtexture_t *cubemaptexture;
3810         char name[256];
3811         // must start 0 so the first loadimagepixels has no requested width/height
3812         cubemapsize = 0;
3813         cubemappixels = NULL;
3814         cubemaptexture = NULL;
3815         // keep trying different suffix groups (posx, px, rt) until one loads
3816         for (j = 0;j < 3 && !cubemappixels;j++)
3817         {
3818                 // load the 6 images in the suffix group
3819                 for (i = 0;i < 6;i++)
3820                 {
3821                         // generate an image name based on the base and and suffix
3822                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3823                         // load it
3824                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3825                         {
3826                                 // an image loaded, make sure width and height are equal
3827                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3828                                 {
3829                                         // if this is the first image to load successfully, allocate the cubemap memory
3830                                         if (!cubemappixels && image_width >= 1)
3831                                         {
3832                                                 cubemapsize = image_width;
3833                                                 // note this clears to black, so unavailable sides are black
3834                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3835                                         }
3836                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3837                                         if (cubemappixels)
3838                                                 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);
3839                                 }
3840                                 else
3841                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3842                                 // free the image
3843                                 Mem_Free(image_buffer);
3844                         }
3845                 }
3846         }
3847         // if a cubemap loaded, upload it
3848         if (cubemappixels)
3849         {
3850                 if (developer_loading.integer)
3851                         Con_Printf("loading cubemap \"%s\"\n", basename);
3852
3853                 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);
3854                 Mem_Free(cubemappixels);
3855         }
3856         else
3857         {
3858                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3859                 if (developer_loading.integer)
3860                 {
3861                         Con_Printf("(tried tried images ");
3862                         for (j = 0;j < 3;j++)
3863                                 for (i = 0;i < 6;i++)
3864                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3865                         Con_Print(" and was unable to find any of them).\n");
3866                 }
3867         }
3868         return cubemaptexture;
3869 }
3870
3871 rtexture_t *R_GetCubemap(const char *basename)
3872 {
3873         int i;
3874         for (i = 0;i < r_texture_numcubemaps;i++)
3875                 if (r_texture_cubemaps[i] != NULL)
3876                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3877                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3878         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3879                 return r_texture_whitecube;
3880         r_texture_numcubemaps++;
3881         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3882         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3883         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3884         return r_texture_cubemaps[i]->texture;
3885 }
3886
3887 void R_FreeCubemap(const char *basename)
3888 {
3889         int i;
3890
3891         for (i = 0;i < r_texture_numcubemaps;i++)
3892         {
3893                 if (r_texture_cubemaps[i] != NULL)
3894                 {
3895                         if (r_texture_cubemaps[i]->texture)
3896                         {
3897                                 if (developer_loading.integer)
3898                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3899                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3900                                 Mem_Free(r_texture_cubemaps[i]);
3901                                 r_texture_cubemaps[i] = NULL;
3902                         }
3903                 }
3904         }
3905 }
3906
3907 void R_FreeCubemaps(void)
3908 {
3909         int i;
3910         for (i = 0;i < r_texture_numcubemaps;i++)
3911         {
3912                 if (developer_loading.integer)
3913                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3914                 if (r_texture_cubemaps[i] != NULL)
3915                 {
3916                         if (r_texture_cubemaps[i]->texture)
3917                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3918                         Mem_Free(r_texture_cubemaps[i]);
3919                 }
3920         }
3921         r_texture_numcubemaps = 0;
3922 }
3923
3924 void R_Main_FreeViewCache(void)
3925 {
3926         if (r_refdef.viewcache.entityvisible)
3927                 Mem_Free(r_refdef.viewcache.entityvisible);
3928         if (r_refdef.viewcache.world_pvsbits)
3929                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3930         if (r_refdef.viewcache.world_leafvisible)
3931                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3932         if (r_refdef.viewcache.world_surfacevisible)
3933                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3934         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3935 }
3936
3937 void R_Main_ResizeViewCache(void)
3938 {
3939         int numentities = r_refdef.scene.numentities;
3940         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3941         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3942         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3943         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3944         if (r_refdef.viewcache.maxentities < numentities)
3945         {
3946                 r_refdef.viewcache.maxentities = numentities;
3947                 if (r_refdef.viewcache.entityvisible)
3948                         Mem_Free(r_refdef.viewcache.entityvisible);
3949                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3950         }
3951         if (r_refdef.viewcache.world_numclusters != numclusters)
3952         {
3953                 r_refdef.viewcache.world_numclusters = numclusters;
3954                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3955                 if (r_refdef.viewcache.world_pvsbits)
3956                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3957                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3958         }
3959         if (r_refdef.viewcache.world_numleafs != numleafs)
3960         {
3961                 r_refdef.viewcache.world_numleafs = numleafs;
3962                 if (r_refdef.viewcache.world_leafvisible)
3963                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3964                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3965         }
3966         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3967         {
3968                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3969                 if (r_refdef.viewcache.world_surfacevisible)
3970                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3971                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3972         }
3973 }
3974
3975 extern rtexture_t *loadingscreentexture;
3976 void gl_main_start(void)
3977 {
3978         loadingscreentexture = NULL;
3979         r_texture_blanknormalmap = NULL;
3980         r_texture_white = NULL;
3981         r_texture_grey128 = NULL;
3982         r_texture_black = NULL;
3983         r_texture_whitecube = NULL;
3984         r_texture_normalizationcube = NULL;
3985         r_texture_fogattenuation = NULL;
3986         r_texture_fogheighttexture = NULL;
3987         r_texture_gammaramps = NULL;
3988         r_texture_numcubemaps = 0;
3989
3990         r_loaddds = r_texture_dds_load.integer != 0;
3991         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3992
3993         switch(vid.renderpath)
3994         {
3995         case RENDERPATH_GL20:
3996         case RENDERPATH_D3D9:
3997         case RENDERPATH_D3D10:
3998         case RENDERPATH_D3D11:
3999         case RENDERPATH_SOFT:
4000         case RENDERPATH_GLES2:
4001                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4002                 Cvar_SetValueQuick(&gl_combine, 1);
4003                 Cvar_SetValueQuick(&r_glsl, 1);
4004                 r_loadnormalmap = true;
4005                 r_loadgloss = true;
4006                 r_loadfog = false;
4007                 break;
4008         case RENDERPATH_GL13:
4009         case RENDERPATH_GLES1:
4010                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4011                 Cvar_SetValueQuick(&gl_combine, 1);
4012                 Cvar_SetValueQuick(&r_glsl, 0);
4013                 r_loadnormalmap = false;
4014                 r_loadgloss = false;
4015                 r_loadfog = true;
4016                 break;
4017         case RENDERPATH_GL11:
4018                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4019                 Cvar_SetValueQuick(&gl_combine, 0);
4020                 Cvar_SetValueQuick(&r_glsl, 0);
4021                 r_loadnormalmap = false;
4022                 r_loadgloss = false;
4023                 r_loadfog = true;
4024                 break;
4025         }
4026
4027         R_AnimCache_Free();
4028         R_FrameData_Reset();
4029
4030         r_numqueries = 0;
4031         r_maxqueries = 0;
4032         memset(r_queries, 0, sizeof(r_queries));
4033
4034         r_qwskincache = NULL;
4035         r_qwskincache_size = 0;
4036
4037         // due to caching of texture_t references, the collision cache must be reset
4038         Collision_Cache_Reset(true);
4039
4040         // set up r_skinframe loading system for textures
4041         memset(&r_skinframe, 0, sizeof(r_skinframe));
4042         r_skinframe.loadsequence = 1;
4043         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4044
4045         r_main_texturepool = R_AllocTexturePool();
4046         R_BuildBlankTextures();
4047         R_BuildNoTexture();
4048         if (vid.support.arb_texture_cube_map)
4049         {
4050                 R_BuildWhiteCube();
4051                 R_BuildNormalizationCube();
4052         }
4053         r_texture_fogattenuation = NULL;
4054         r_texture_fogheighttexture = NULL;
4055         r_texture_gammaramps = NULL;
4056         //r_texture_fogintensity = NULL;
4057         memset(&r_fb, 0, sizeof(r_fb));
4058         r_glsl_permutation = NULL;
4059         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4060         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4061         glslshaderstring = NULL;
4062 #ifdef SUPPORTD3D
4063         r_hlsl_permutation = NULL;
4064         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4065         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4066 #endif
4067         hlslshaderstring = NULL;
4068         memset(&r_svbsp, 0, sizeof (r_svbsp));
4069
4070         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4071         r_texture_numcubemaps = 0;
4072
4073         r_refdef.fogmasktable_density = 0;
4074 }
4075
4076 void gl_main_shutdown(void)
4077 {
4078         R_AnimCache_Free();
4079         R_FrameData_Reset();
4080
4081         R_Main_FreeViewCache();
4082
4083         switch(vid.renderpath)
4084         {
4085         case RENDERPATH_GL11:
4086         case RENDERPATH_GL13:
4087         case RENDERPATH_GL20:
4088         case RENDERPATH_GLES1:
4089         case RENDERPATH_GLES2:
4090 #ifdef GL_SAMPLES_PASSED_ARB
4091                 if (r_maxqueries)
4092                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4093 #endif
4094                 break;
4095         case RENDERPATH_D3D9:
4096                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4097                 break;
4098         case RENDERPATH_D3D10:
4099                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4100                 break;
4101         case RENDERPATH_D3D11:
4102                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4103                 break;
4104         case RENDERPATH_SOFT:
4105                 break;
4106         }
4107
4108         r_numqueries = 0;
4109         r_maxqueries = 0;
4110         memset(r_queries, 0, sizeof(r_queries));
4111
4112         r_qwskincache = NULL;
4113         r_qwskincache_size = 0;
4114
4115         // clear out the r_skinframe state
4116         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4117         memset(&r_skinframe, 0, sizeof(r_skinframe));
4118
4119         if (r_svbsp.nodes)
4120                 Mem_Free(r_svbsp.nodes);
4121         memset(&r_svbsp, 0, sizeof (r_svbsp));
4122         R_FreeTexturePool(&r_main_texturepool);
4123         loadingscreentexture = NULL;
4124         r_texture_blanknormalmap = NULL;
4125         r_texture_white = NULL;
4126         r_texture_grey128 = NULL;
4127         r_texture_black = NULL;
4128         r_texture_whitecube = NULL;
4129         r_texture_normalizationcube = NULL;
4130         r_texture_fogattenuation = NULL;
4131         r_texture_fogheighttexture = NULL;
4132         r_texture_gammaramps = NULL;
4133         r_texture_numcubemaps = 0;
4134         //r_texture_fogintensity = NULL;
4135         memset(&r_fb, 0, sizeof(r_fb));
4136         R_GLSL_Restart_f();
4137
4138         r_glsl_permutation = NULL;
4139         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4140         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4141         glslshaderstring = NULL;
4142 #ifdef SUPPORTD3D
4143         r_hlsl_permutation = NULL;
4144         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4145         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4146 #endif
4147         hlslshaderstring = NULL;
4148 }
4149
4150 extern void CL_ParseEntityLump(char *entitystring);
4151 void gl_main_newmap(void)
4152 {
4153         // FIXME: move this code to client
4154         char *entities, entname[MAX_QPATH];
4155         if (r_qwskincache)
4156                 Mem_Free(r_qwskincache);
4157         r_qwskincache = NULL;
4158         r_qwskincache_size = 0;
4159         if (cl.worldmodel)
4160         {
4161                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4162                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4163                 {
4164                         CL_ParseEntityLump(entities);
4165                         Mem_Free(entities);
4166                         return;
4167                 }
4168                 if (cl.worldmodel->brush.entities)
4169                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4170         }
4171         R_Main_FreeViewCache();
4172
4173         R_FrameData_Reset();
4174 }
4175
4176 void GL_Main_Init(void)
4177 {
4178         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4179
4180         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4181         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4182         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4183         if (gamemode == GAME_NEHAHRA)
4184         {
4185                 Cvar_RegisterVariable (&gl_fogenable);
4186                 Cvar_RegisterVariable (&gl_fogdensity);
4187                 Cvar_RegisterVariable (&gl_fogred);
4188                 Cvar_RegisterVariable (&gl_foggreen);
4189                 Cvar_RegisterVariable (&gl_fogblue);
4190                 Cvar_RegisterVariable (&gl_fogstart);
4191                 Cvar_RegisterVariable (&gl_fogend);
4192                 Cvar_RegisterVariable (&gl_skyclip);
4193         }
4194         Cvar_RegisterVariable(&r_motionblur);
4195         Cvar_RegisterVariable(&r_damageblur);
4196         Cvar_RegisterVariable(&r_motionblur_averaging);
4197         Cvar_RegisterVariable(&r_motionblur_randomize);
4198         Cvar_RegisterVariable(&r_motionblur_minblur);
4199         Cvar_RegisterVariable(&r_motionblur_maxblur);
4200         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4201         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4202         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4203         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4204         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4205         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4206         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4207         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4208         Cvar_RegisterVariable(&r_equalize_entities_by);
4209         Cvar_RegisterVariable(&r_equalize_entities_to);
4210         Cvar_RegisterVariable(&r_depthfirst);
4211         Cvar_RegisterVariable(&r_useinfinitefarclip);
4212         Cvar_RegisterVariable(&r_farclip_base);
4213         Cvar_RegisterVariable(&r_farclip_world);
4214         Cvar_RegisterVariable(&r_nearclip);
4215         Cvar_RegisterVariable(&r_deformvertexes);
4216         Cvar_RegisterVariable(&r_transparent);
4217         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4218         Cvar_RegisterVariable(&r_showoverdraw);
4219         Cvar_RegisterVariable(&r_showbboxes);
4220         Cvar_RegisterVariable(&r_showsurfaces);
4221         Cvar_RegisterVariable(&r_showtris);
4222         Cvar_RegisterVariable(&r_shownormals);
4223         Cvar_RegisterVariable(&r_showlighting);
4224         Cvar_RegisterVariable(&r_showshadowvolumes);
4225         Cvar_RegisterVariable(&r_showcollisionbrushes);
4226         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4227         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4228         Cvar_RegisterVariable(&r_showdisabledepthtest);
4229         Cvar_RegisterVariable(&r_drawportals);
4230         Cvar_RegisterVariable(&r_drawentities);
4231         Cvar_RegisterVariable(&r_draw2d);
4232         Cvar_RegisterVariable(&r_drawworld);
4233         Cvar_RegisterVariable(&r_cullentities_trace);
4234         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4235         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4236         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4237         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4238         Cvar_RegisterVariable(&r_sortentities);
4239         Cvar_RegisterVariable(&r_drawviewmodel);
4240         Cvar_RegisterVariable(&r_drawexteriormodel);
4241         Cvar_RegisterVariable(&r_speeds);
4242         Cvar_RegisterVariable(&r_fullbrights);
4243         Cvar_RegisterVariable(&r_wateralpha);
4244         Cvar_RegisterVariable(&r_dynamic);
4245         Cvar_RegisterVariable(&r_fakelight);
4246         Cvar_RegisterVariable(&r_fakelight_intensity);
4247         Cvar_RegisterVariable(&r_fullbright);
4248         Cvar_RegisterVariable(&r_shadows);
4249         Cvar_RegisterVariable(&r_shadows_darken);
4250         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4251         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4252         Cvar_RegisterVariable(&r_shadows_throwdistance);
4253         Cvar_RegisterVariable(&r_shadows_throwdirection);
4254         Cvar_RegisterVariable(&r_shadows_focus);
4255         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4256         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4257         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4258         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4259         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4260         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4261         Cvar_RegisterVariable(&r_fog_exp2);
4262         Cvar_RegisterVariable(&r_fog_clear);
4263         Cvar_RegisterVariable(&r_drawfog);
4264         Cvar_RegisterVariable(&r_transparentdepthmasking);
4265         Cvar_RegisterVariable(&r_transparent_sortmindist);
4266         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4267         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4268         Cvar_RegisterVariable(&r_texture_dds_load);
4269         Cvar_RegisterVariable(&r_texture_dds_save);
4270         Cvar_RegisterVariable(&r_textureunits);
4271         Cvar_RegisterVariable(&gl_combine);
4272         Cvar_RegisterVariable(&r_viewfbo);
4273         Cvar_RegisterVariable(&r_viewscale);
4274         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4275         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4276         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4277         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4278         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4279         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4280         Cvar_RegisterVariable(&r_glsl);
4281         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4282         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4283         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4284         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4285         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4286         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4287         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4288         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4289         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4290         Cvar_RegisterVariable(&r_glsl_postprocess);
4291         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4292         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4293         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4294         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4295         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4296         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4297         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4298         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4299
4300         Cvar_RegisterVariable(&r_water);
4301         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4302         Cvar_RegisterVariable(&r_water_clippingplanebias);
4303         Cvar_RegisterVariable(&r_water_refractdistort);
4304         Cvar_RegisterVariable(&r_water_reflectdistort);
4305         Cvar_RegisterVariable(&r_water_scissormode);
4306         Cvar_RegisterVariable(&r_water_lowquality);
4307         Cvar_RegisterVariable(&r_water_hideplayer);
4308         Cvar_RegisterVariable(&r_water_fbo);
4309
4310         Cvar_RegisterVariable(&r_lerpsprites);
4311         Cvar_RegisterVariable(&r_lerpmodels);
4312         Cvar_RegisterVariable(&r_lerplightstyles);
4313         Cvar_RegisterVariable(&r_waterscroll);
4314         Cvar_RegisterVariable(&r_bloom);
4315         Cvar_RegisterVariable(&r_bloom_colorscale);
4316         Cvar_RegisterVariable(&r_bloom_brighten);
4317         Cvar_RegisterVariable(&r_bloom_blur);
4318         Cvar_RegisterVariable(&r_bloom_resolution);
4319         Cvar_RegisterVariable(&r_bloom_colorexponent);
4320         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4321         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4322         Cvar_RegisterVariable(&r_hdr_glowintensity);
4323         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4324         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4325         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4326         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4327         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4328         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4329         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4330         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4331         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4332         Cvar_RegisterVariable(&developer_texturelogging);
4333         Cvar_RegisterVariable(&gl_lightmaps);
4334         Cvar_RegisterVariable(&r_test);
4335         Cvar_RegisterVariable(&r_glsl_saturation);
4336         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4337         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4338         Cvar_RegisterVariable(&r_framedatasize);
4339         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4340                 Cvar_SetValue("r_fullbrights", 0);
4341         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4342 }
4343
4344 extern void R_Textures_Init(void);
4345 extern void GL_Draw_Init(void);
4346 extern void GL_Main_Init(void);
4347 extern void R_Shadow_Init(void);
4348 extern void R_Sky_Init(void);
4349 extern void GL_Surf_Init(void);
4350 extern void R_Particles_Init(void);
4351 extern void R_Explosion_Init(void);
4352 extern void gl_backend_init(void);
4353 extern void Sbar_Init(void);
4354 extern void R_LightningBeams_Init(void);
4355 extern void Mod_RenderInit(void);
4356 extern void Font_Init(void);
4357
4358 void Render_Init(void)
4359 {
4360         gl_backend_init();
4361         R_Textures_Init();
4362         GL_Main_Init();
4363         Font_Init();
4364         GL_Draw_Init();
4365         R_Shadow_Init();
4366         R_Sky_Init();
4367         GL_Surf_Init();
4368         Sbar_Init();
4369         R_Particles_Init();
4370         R_Explosion_Init();
4371         R_LightningBeams_Init();
4372         Mod_RenderInit();
4373 }
4374
4375 /*
4376 ===============
4377 GL_Init
4378 ===============
4379 */
4380 #ifndef USE_GLES2
4381 extern char *ENGINE_EXTENSIONS;
4382 void GL_Init (void)
4383 {
4384         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4385         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4386         gl_version = (const char *)qglGetString(GL_VERSION);
4387         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4388
4389         if (!gl_extensions)
4390                 gl_extensions = "";
4391         if (!gl_platformextensions)
4392                 gl_platformextensions = "";
4393
4394         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4395         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4396         Con_Printf("GL_VERSION: %s\n", gl_version);
4397         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4398         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4399
4400         VID_CheckExtensions();
4401
4402         // LordHavoc: report supported extensions
4403         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4404
4405         // clear to black (loading plaque will be seen over this)
4406         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4407 }
4408 #endif
4409
4410 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4411 {
4412         int i;
4413         mplane_t *p;
4414         if (r_trippy.integer)
4415                 return false;
4416         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4417         {
4418                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4419                 if (i == 4)
4420                         continue;
4421                 p = r_refdef.view.frustum + i;
4422                 switch(p->signbits)
4423                 {
4424                 default:
4425                 case 0:
4426                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4427                                 return true;
4428                         break;
4429                 case 1:
4430                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 2:
4434                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 3:
4438                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 4:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 5:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 6:
4450                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 7:
4454                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 }
4458         }
4459         return false;
4460 }
4461
4462 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4463 {
4464         int i;
4465         const mplane_t *p;
4466         if (r_trippy.integer)
4467                 return false;
4468         for (i = 0;i < numplanes;i++)
4469         {
4470                 p = planes + i;
4471                 switch(p->signbits)
4472                 {
4473                 default:
4474                 case 0:
4475                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 case 1:
4479                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 case 2:
4483                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 3:
4487                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 4:
4491                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 5:
4495                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 6:
4499                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 case 7:
4503                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4504                                 return true;
4505                         break;
4506                 }
4507         }
4508         return false;
4509 }
4510
4511 //==================================================================================
4512
4513 // LordHavoc: this stores temporary data used within the same frame
4514
4515 typedef struct r_framedata_mem_s
4516 {
4517         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4518         size_t size; // how much usable space
4519         size_t current; // how much space in use
4520         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4521         size_t wantedsize; // how much space was allocated
4522         unsigned char *data; // start of real data (16byte aligned)
4523 }
4524 r_framedata_mem_t;
4525
4526 static r_framedata_mem_t *r_framedata_mem;
4527
4528 void R_FrameData_Reset(void)
4529 {
4530         while (r_framedata_mem)
4531         {
4532                 r_framedata_mem_t *next = r_framedata_mem->purge;
4533                 Mem_Free(r_framedata_mem);
4534                 r_framedata_mem = next;
4535         }
4536 }
4537
4538 void R_FrameData_Resize(void)
4539 {
4540         size_t wantedsize;
4541         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4542         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4543         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4544         {
4545                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4546                 newmem->wantedsize = wantedsize;
4547                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4548                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4549                 newmem->current = 0;
4550                 newmem->mark = 0;
4551                 newmem->purge = r_framedata_mem;
4552                 r_framedata_mem = newmem;
4553         }
4554 }
4555
4556 void R_FrameData_NewFrame(void)
4557 {
4558         R_FrameData_Resize();
4559         if (!r_framedata_mem)
4560                 return;
4561         // if we ran out of space on the last frame, free the old memory now
4562         while (r_framedata_mem->purge)
4563         {
4564                 // repeatedly remove the second item in the list, leaving only head
4565                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4566                 Mem_Free(r_framedata_mem->purge);
4567                 r_framedata_mem->purge = next;
4568         }
4569         // reset the current mem pointer
4570         r_framedata_mem->current = 0;
4571         r_framedata_mem->mark = 0;
4572 }
4573
4574 void *R_FrameData_Alloc(size_t size)
4575 {
4576         void *data;
4577
4578         // align to 16 byte boundary - the data pointer is already aligned, so we
4579         // only need to ensure the size of every allocation is also aligned
4580         size = (size + 15) & ~15;
4581
4582         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4583         {
4584                 // emergency - we ran out of space, allocate more memory
4585                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4586                 R_FrameData_Resize();
4587         }
4588
4589         data = r_framedata_mem->data + r_framedata_mem->current;
4590         r_framedata_mem->current += size;
4591
4592         // count the usage for stats
4593         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4594         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4595
4596         return (void *)data;
4597 }
4598
4599 void *R_FrameData_Store(size_t size, void *data)
4600 {
4601         void *d = R_FrameData_Alloc(size);
4602         if (d && data)
4603                 memcpy(d, data, size);
4604         return d;
4605 }
4606
4607 void R_FrameData_SetMark(void)
4608 {
4609         if (!r_framedata_mem)
4610                 return;
4611         r_framedata_mem->mark = r_framedata_mem->current;
4612 }
4613
4614 void R_FrameData_ReturnToMark(void)
4615 {
4616         if (!r_framedata_mem)
4617                 return;
4618         r_framedata_mem->current = r_framedata_mem->mark;
4619 }
4620
4621 //==================================================================================
4622
4623 // LordHavoc: animcache originally written by Echon, rewritten since then
4624
4625 /**
4626  * Animation cache prevents re-generating mesh data for an animated model
4627  * multiple times in one frame for lighting, shadowing, reflections, etc.
4628  */
4629
4630 void R_AnimCache_Free(void)
4631 {
4632 }
4633
4634 void R_AnimCache_ClearCache(void)
4635 {
4636         int i;
4637         entity_render_t *ent;
4638
4639         for (i = 0;i < r_refdef.scene.numentities;i++)
4640         {
4641                 ent = r_refdef.scene.entities[i];
4642                 ent->animcache_vertex3f = NULL;
4643                 ent->animcache_normal3f = NULL;
4644                 ent->animcache_svector3f = NULL;
4645                 ent->animcache_tvector3f = NULL;
4646                 ent->animcache_vertexmesh = NULL;
4647                 ent->animcache_vertex3fbuffer = NULL;
4648                 ent->animcache_vertexmeshbuffer = NULL;
4649         }
4650 }
4651
4652 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4653 {
4654         int i;
4655
4656         // check if we need the meshbuffers
4657         if (!vid.useinterleavedarrays)
4658                 return;
4659
4660         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4661                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4662         // TODO: upload vertex3f buffer?
4663         if (ent->animcache_vertexmesh)
4664         {
4665                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4666                 for (i = 0;i < numvertices;i++)
4667                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4668                 if (ent->animcache_svector3f)
4669                         for (i = 0;i < numvertices;i++)
4670                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4671                 if (ent->animcache_tvector3f)
4672                         for (i = 0;i < numvertices;i++)
4673                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4674                 if (ent->animcache_normal3f)
4675                         for (i = 0;i < numvertices;i++)
4676                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4677                 // TODO: upload vertexmeshbuffer?
4678         }
4679 }
4680
4681 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4682 {
4683         dp_model_t *model = ent->model;
4684         int numvertices;
4685         // see if it's already cached this frame
4686         if (ent->animcache_vertex3f)
4687         {
4688                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4689                 if (wantnormals || wanttangents)
4690                 {
4691                         if (ent->animcache_normal3f)
4692                                 wantnormals = false;
4693                         if (ent->animcache_svector3f)
4694                                 wanttangents = false;
4695                         if (wantnormals || wanttangents)
4696                         {
4697                                 numvertices = model->surfmesh.num_vertices;
4698                                 if (wantnormals)
4699                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4700                                 if (wanttangents)
4701                                 {
4702                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4703                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4704                                 }
4705                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4706                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4707                         }
4708                 }
4709         }
4710         else
4711         {
4712                 // see if this ent is worth caching
4713                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4714                         return false;
4715                 // get some memory for this entity and generate mesh data
4716                 numvertices = model->surfmesh.num_vertices;
4717                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4718                 if (wantnormals)
4719                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4720                 if (wanttangents)
4721                 {
4722                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4723                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4724                 }
4725                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4726                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4727         }
4728         return true;
4729 }
4730
4731 void R_AnimCache_CacheVisibleEntities(void)
4732 {
4733         int i;
4734         qboolean wantnormals = true;
4735         qboolean wanttangents = !r_showsurfaces.integer;
4736
4737         switch(vid.renderpath)
4738         {
4739         case RENDERPATH_GL20:
4740         case RENDERPATH_D3D9:
4741         case RENDERPATH_D3D10:
4742         case RENDERPATH_D3D11:
4743         case RENDERPATH_GLES2:
4744                 break;
4745         case RENDERPATH_GL11:
4746         case RENDERPATH_GL13:
4747         case RENDERPATH_GLES1:
4748                 wanttangents = false;
4749                 break;
4750         case RENDERPATH_SOFT:
4751                 break;
4752         }
4753
4754         if (r_shownormals.integer)
4755                 wanttangents = wantnormals = true;
4756
4757         // TODO: thread this
4758         // NOTE: R_PrepareRTLights() also caches entities
4759
4760         for (i = 0;i < r_refdef.scene.numentities;i++)
4761                 if (r_refdef.viewcache.entityvisible[i])
4762                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4763 }
4764
4765 //==================================================================================
4766
4767 extern cvar_t r_overheadsprites_pushback;
4768
4769 static void R_View_UpdateEntityLighting (void)
4770 {
4771         int i;
4772         entity_render_t *ent;
4773         vec3_t tempdiffusenormal, avg;
4774         vec_t f, fa, fd, fdd;
4775         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4776
4777         for (i = 0;i < r_refdef.scene.numentities;i++)
4778         {
4779                 ent = r_refdef.scene.entities[i];
4780
4781                 // skip unseen models and models that updated by CSQC
4782                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4783                         continue;
4784
4785                 // skip bsp models
4786                 if (ent->model && ent->model->brush.num_leafs)
4787                 {
4788                         // TODO: use modellight for r_ambient settings on world?
4789                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4790                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4791                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4792                         continue;
4793                 }
4794
4795                 // fetch the lighting from the worldmodel data
4796                 VectorClear(ent->modellight_ambient);
4797                 VectorClear(ent->modellight_diffuse);
4798                 VectorClear(tempdiffusenormal);
4799                 if (ent->flags & RENDER_LIGHT)
4800                 {
4801                         vec3_t org;
4802                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4803
4804                         // complete lightning for lit sprites
4805                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4806                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4807                         {
4808                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4809                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4810                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4811                         }
4812                         else
4813                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4814
4815                         if(ent->flags & RENDER_EQUALIZE)
4816                         {
4817                                 // first fix up ambient lighting...
4818                                 if(r_equalize_entities_minambient.value > 0)
4819                                 {
4820                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4821                                         if(fd > 0)
4822                                         {
4823                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4824                                                 if(fa < r_equalize_entities_minambient.value * fd)
4825                                                 {
4826                                                         // solve:
4827                                                         //   fa'/fd' = minambient
4828                                                         //   fa'+0.25*fd' = fa+0.25*fd
4829                                                         //   ...
4830                                                         //   fa' = fd' * minambient
4831                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4832                                                         //   ...
4833                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4834                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4835                                                         //   ...
4836                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4837                                                         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
4838                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4839                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4840                                                 }
4841                                         }
4842                                 }
4843
4844                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4845                                 {
4846                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4847                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4848                                         f = fa + 0.25 * fd;
4849                                         if(f > 0)
4850                                         {
4851                                                 // adjust brightness and saturation to target
4852                                                 avg[0] = avg[1] = avg[2] = fa / f;
4853                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4854                                                 avg[0] = avg[1] = avg[2] = fd / f;
4855                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4856                                         }
4857                                 }
4858                         }
4859                 }
4860                 else // highly rare
4861                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4862
4863                 // move the light direction into modelspace coordinates for lighting code
4864                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4865                 if(VectorLength2(ent->modellight_lightdir) == 0)
4866                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4867                 VectorNormalize(ent->modellight_lightdir);
4868         }
4869 }
4870
4871 #define MAX_LINEOFSIGHTTRACES 64
4872
4873 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4874 {
4875         int i;
4876         vec3_t boxmins, boxmaxs;
4877         vec3_t start;
4878         vec3_t end;
4879         dp_model_t *model = r_refdef.scene.worldmodel;
4880
4881         if (!model || !model->brush.TraceLineOfSight)
4882                 return true;
4883
4884         // expand the box a little
4885         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4886         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4887         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4888         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4889         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4890         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4891
4892         // return true if eye is inside enlarged box
4893         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4894                 return true;
4895
4896         // try center
4897         VectorCopy(eye, start);
4898         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4899         if (model->brush.TraceLineOfSight(model, start, end))
4900                 return true;
4901
4902         // try various random positions
4903         for (i = 0;i < numsamples;i++)
4904         {
4905                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4906                 if (model->brush.TraceLineOfSight(model, start, end))
4907                         return true;
4908         }
4909
4910         return false;
4911 }
4912
4913
4914 static void R_View_UpdateEntityVisible (void)
4915 {
4916         int i;
4917         int renderimask;
4918         int samples;
4919         entity_render_t *ent;
4920
4921         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4922                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4923                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4924                 :                                                          RENDER_EXTERIORMODEL;
4925         if (!r_drawviewmodel.integer)
4926                 renderimask |= RENDER_VIEWMODEL;
4927         if (!r_drawexteriormodel.integer)
4928                 renderimask |= RENDER_EXTERIORMODEL;
4929         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4930         {
4931                 // worldmodel can check visibility
4932                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4933                 for (i = 0;i < r_refdef.scene.numentities;i++)
4934                 {
4935                         ent = r_refdef.scene.entities[i];
4936                         if (!(ent->flags & renderimask))
4937                         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)))
4938                         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))
4939                                 r_refdef.viewcache.entityvisible[i] = true;
4940                 }
4941         }
4942         else
4943         {
4944                 // no worldmodel or it can't check visibility
4945                 for (i = 0;i < r_refdef.scene.numentities;i++)
4946                 {
4947                         ent = r_refdef.scene.entities[i];
4948                         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));
4949                 }
4950         }
4951         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4952                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
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                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4960                         {
4961                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4962                                 if (samples < 0)
4963                                         continue; // temp entities do pvs only
4964                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4965                                         ent->last_trace_visibility = realtime;
4966                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4967                                         r_refdef.viewcache.entityvisible[i] = 0;
4968                         }
4969                 }
4970         }
4971 }
4972
4973 /// only used if skyrendermasked, and normally returns false
4974 int R_DrawBrushModelsSky (void)
4975 {
4976         int i, sky;
4977         entity_render_t *ent;
4978
4979         sky = false;
4980         for (i = 0;i < r_refdef.scene.numentities;i++)
4981         {
4982                 if (!r_refdef.viewcache.entityvisible[i])
4983                         continue;
4984                 ent = r_refdef.scene.entities[i];
4985                 if (!ent->model || !ent->model->DrawSky)
4986                         continue;
4987                 ent->model->DrawSky(ent);
4988                 sky = true;
4989         }
4990         return sky;
4991 }
4992
4993 static void R_DrawNoModel(entity_render_t *ent);
4994 static void R_DrawModels(void)
4995 {
4996         int i;
4997         entity_render_t *ent;
4998
4999         for (i = 0;i < r_refdef.scene.numentities;i++)
5000         {
5001                 if (!r_refdef.viewcache.entityvisible[i])
5002                         continue;
5003                 ent = r_refdef.scene.entities[i];
5004                 r_refdef.stats.entities++;
5005                 /*
5006                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5007                 {
5008                         vec3_t f, l, u, o;
5009                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5010                         Con_Printf("R_DrawModels\n");
5011                         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]);
5012                         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);
5013                         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);
5014                 }
5015                 */
5016                 if (ent->model && ent->model->Draw != NULL)
5017                         ent->model->Draw(ent);
5018                 else
5019                         R_DrawNoModel(ent);
5020         }
5021 }
5022
5023 static void R_DrawModelsDepth(void)
5024 {
5025         int i;
5026         entity_render_t *ent;
5027
5028         for (i = 0;i < r_refdef.scene.numentities;i++)
5029         {
5030                 if (!r_refdef.viewcache.entityvisible[i])
5031                         continue;
5032                 ent = r_refdef.scene.entities[i];
5033                 if (ent->model && ent->model->DrawDepth != NULL)
5034                         ent->model->DrawDepth(ent);
5035         }
5036 }
5037
5038 static void R_DrawModelsDebug(void)
5039 {
5040         int i;
5041         entity_render_t *ent;
5042
5043         for (i = 0;i < r_refdef.scene.numentities;i++)
5044         {
5045                 if (!r_refdef.viewcache.entityvisible[i])
5046                         continue;
5047                 ent = r_refdef.scene.entities[i];
5048                 if (ent->model && ent->model->DrawDebug != NULL)
5049                         ent->model->DrawDebug(ent);
5050         }
5051 }
5052
5053 static void R_DrawModelsAddWaterPlanes(void)
5054 {
5055         int i;
5056         entity_render_t *ent;
5057
5058         for (i = 0;i < r_refdef.scene.numentities;i++)
5059         {
5060                 if (!r_refdef.viewcache.entityvisible[i])
5061                         continue;
5062                 ent = r_refdef.scene.entities[i];
5063                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5064                         ent->model->DrawAddWaterPlanes(ent);
5065         }
5066 }
5067
5068 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}};
5069
5070 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5071 {
5072         if (r_hdr_irisadaptation.integer)
5073         {
5074                 vec3_t p;
5075                 vec3_t ambient;
5076                 vec3_t diffuse;
5077                 vec3_t diffusenormal;
5078                 vec3_t forward;
5079                 vec_t brightness = 0.0f;
5080                 vec_t goal;
5081                 vec_t current;
5082                 vec_t d;
5083                 int c;
5084                 VectorCopy(r_refdef.view.forward, forward);
5085                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5086                 {
5087                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5088                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5089                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5090                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5091                         d = DotProduct(forward, diffusenormal);
5092                         brightness += VectorLength(ambient);
5093                         if (d > 0)
5094                                 brightness += d * VectorLength(diffuse);
5095                 }
5096                 brightness *= 1.0f / c;
5097                 brightness += 0.00001f; // make sure it's never zero
5098                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5099                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5100                 current = r_hdr_irisadaptation_value.value;
5101                 if (current < goal)
5102                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5103                 else if (current > goal)
5104                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5105                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5106                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5107         }
5108         else if (r_hdr_irisadaptation_value.value != 1.0f)
5109                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5110 }
5111
5112 static void R_View_SetFrustum(const int *scissor)
5113 {
5114         int i;
5115         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5116         vec3_t forward, left, up, origin, v;
5117
5118         if(scissor)
5119         {
5120                 // flipped x coordinates (because x points left here)
5121                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5122                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5123
5124                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5125                 switch(vid.renderpath)
5126                 {
5127                         case RENDERPATH_D3D9:
5128                         case RENDERPATH_D3D10:
5129                         case RENDERPATH_D3D11:
5130                                 // non-flipped y coordinates
5131                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5132                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5133                                 break;
5134                         case RENDERPATH_SOFT:
5135                         case RENDERPATH_GL11:
5136                         case RENDERPATH_GL13:
5137                         case RENDERPATH_GL20:
5138                         case RENDERPATH_GLES1:
5139                         case RENDERPATH_GLES2:
5140                                 // non-flipped y coordinates
5141                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5142                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5143                                 break;
5144                 }
5145         }
5146
5147         // we can't trust r_refdef.view.forward and friends in reflected scenes
5148         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5149
5150 #if 0
5151         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5152         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5153         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5154         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5155         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5156         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5157         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5158         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5159         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5160         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5161         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5162         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5163 #endif
5164
5165 #if 0
5166         zNear = r_refdef.nearclip;
5167         nudge = 1.0 - 1.0 / (1<<23);
5168         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5169         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5170         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5171         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5172         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5173         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5174         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5175         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5176 #endif
5177
5178
5179
5180 #if 0
5181         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5182         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5183         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5184         r_refdef.view.frustum[0].dist = m[15] - m[12];
5185
5186         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5187         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5188         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5189         r_refdef.view.frustum[1].dist = m[15] + m[12];
5190
5191         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5192         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5193         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5194         r_refdef.view.frustum[2].dist = m[15] - m[13];
5195
5196         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5197         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5198         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5199         r_refdef.view.frustum[3].dist = m[15] + m[13];
5200
5201         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5202         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5203         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5204         r_refdef.view.frustum[4].dist = m[15] - m[14];
5205
5206         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5207         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5208         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5209         r_refdef.view.frustum[5].dist = m[15] + m[14];
5210 #endif
5211
5212         if (r_refdef.view.useperspective)
5213         {
5214                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5215                 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]);
5216                 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]);
5217                 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]);
5218                 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]);
5219
5220                 // then the normals from the corners relative to origin
5221                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5222                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5223                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5224                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5225
5226                 // in a NORMAL view, forward cross left == up
5227                 // in a REFLECTED view, forward cross left == down
5228                 // so our cross products above need to be adjusted for a left handed coordinate system
5229                 CrossProduct(forward, left, v);
5230                 if(DotProduct(v, up) < 0)
5231                 {
5232                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5233                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5234                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5235                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5236                 }
5237
5238                 // Leaving those out was a mistake, those were in the old code, and they
5239                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5240                 // I couldn't reproduce it after adding those normalizations. --blub
5241                 VectorNormalize(r_refdef.view.frustum[0].normal);
5242                 VectorNormalize(r_refdef.view.frustum[1].normal);
5243                 VectorNormalize(r_refdef.view.frustum[2].normal);
5244                 VectorNormalize(r_refdef.view.frustum[3].normal);
5245
5246                 // make the corners absolute
5247                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5248                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5249                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5250                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5251
5252                 // one more normal
5253                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5254
5255                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5256                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5257                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5258                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5259                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5260         }
5261         else
5262         {
5263                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5264                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5265                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5266                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5267                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5268                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5269                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5270                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5271                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5272                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5273         }
5274         r_refdef.view.numfrustumplanes = 5;
5275
5276         if (r_refdef.view.useclipplane)
5277         {
5278                 r_refdef.view.numfrustumplanes = 6;
5279                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5280         }
5281
5282         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5283                 PlaneClassify(r_refdef.view.frustum + i);
5284
5285         // LordHavoc: note to all quake engine coders, Quake had a special case
5286         // for 90 degrees which assumed a square view (wrong), so I removed it,
5287         // Quake2 has it disabled as well.
5288
5289         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5290         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5291         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5292         //PlaneClassify(&frustum[0]);
5293
5294         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5295         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5296         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5297         //PlaneClassify(&frustum[1]);
5298
5299         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5300         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5301         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5302         //PlaneClassify(&frustum[2]);
5303
5304         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5305         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5306         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5307         //PlaneClassify(&frustum[3]);
5308
5309         // nearclip plane
5310         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5311         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5312         //PlaneClassify(&frustum[4]);
5313 }
5314
5315 void R_View_UpdateWithScissor(const int *myscissor)
5316 {
5317         R_Main_ResizeViewCache();
5318         R_View_SetFrustum(myscissor);
5319         R_View_WorldVisibility(r_refdef.view.useclipplane);
5320         R_View_UpdateEntityVisible();
5321         R_View_UpdateEntityLighting();
5322         R_AnimCache_CacheVisibleEntities();
5323 }
5324
5325 void R_View_Update(void)
5326 {
5327         R_Main_ResizeViewCache();
5328         R_View_SetFrustum(NULL);
5329         R_View_WorldVisibility(r_refdef.view.useclipplane);
5330         R_View_UpdateEntityVisible();
5331         R_View_UpdateEntityLighting();
5332         R_AnimCache_CacheVisibleEntities();
5333 }
5334
5335 float viewscalefpsadjusted = 1.0f;
5336
5337 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5338 {
5339         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5340         scale = bound(0.03125f, scale, 1.0f);
5341         *outwidth = (int)ceil(width * scale);
5342         *outheight = (int)ceil(height * scale);
5343 }
5344
5345 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5346 {
5347         const float *customclipplane = NULL;
5348         float plane[4];
5349         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5350         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5351         {
5352                 // LordHavoc: couldn't figure out how to make this approach the
5353                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5354                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5355                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5356                         dist = r_refdef.view.clipplane.dist;
5357                 plane[0] = r_refdef.view.clipplane.normal[0];
5358                 plane[1] = r_refdef.view.clipplane.normal[1];
5359                 plane[2] = r_refdef.view.clipplane.normal[2];
5360                 plane[3] = -dist;
5361                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5362         }
5363
5364         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5365         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5366
5367         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5368         if (!r_refdef.view.useperspective)
5369                 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);
5370         else if (vid.stencil && r_useinfinitefarclip.integer)
5371                 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);
5372         else
5373                 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);
5374         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5375         R_SetViewport(&r_refdef.view.viewport);
5376         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5377         {
5378                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5379                 float screenplane[4];
5380                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5381                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5382                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5383                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5384                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5385         }
5386 }
5387
5388 void R_EntityMatrix(const matrix4x4_t *matrix)
5389 {
5390         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5391         {
5392                 gl_modelmatrixchanged = false;
5393                 gl_modelmatrix = *matrix;
5394                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5395                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5396                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5397                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5398                 CHECKGLERROR
5399                 switch(vid.renderpath)
5400                 {
5401                 case RENDERPATH_D3D9:
5402 #ifdef SUPPORTD3D
5403                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5404                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5405 #endif
5406                         break;
5407                 case RENDERPATH_D3D10:
5408                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5409                         break;
5410                 case RENDERPATH_D3D11:
5411                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5412                         break;
5413                 case RENDERPATH_GL11:
5414                 case RENDERPATH_GL13:
5415                 case RENDERPATH_GLES1:
5416                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5417                         break;
5418                 case RENDERPATH_SOFT:
5419                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5420                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5421                         break;
5422                 case RENDERPATH_GL20:
5423                 case RENDERPATH_GLES2:
5424                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5425                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5426                         break;
5427                 }
5428         }
5429 }
5430
5431 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5432 {
5433         r_viewport_t viewport;
5434         DrawQ_Finish();
5435
5436         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5437         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);
5438         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5439         R_SetViewport(&viewport);
5440         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5441         GL_Color(1, 1, 1, 1);
5442         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5443         GL_BlendFunc(GL_ONE, GL_ZERO);
5444         GL_ScissorTest(false);
5445         GL_DepthMask(false);
5446         GL_DepthRange(0, 1);
5447         GL_DepthTest(false);
5448         GL_DepthFunc(GL_LEQUAL);
5449         R_EntityMatrix(&identitymatrix);
5450         R_Mesh_ResetTextureState();
5451         GL_PolygonOffset(0, 0);
5452         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5453         switch(vid.renderpath)
5454         {
5455         case RENDERPATH_GL11:
5456         case RENDERPATH_GL13:
5457         case RENDERPATH_GL20:
5458         case RENDERPATH_GLES1:
5459         case RENDERPATH_GLES2:
5460                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5461                 break;
5462         case RENDERPATH_D3D9:
5463         case RENDERPATH_D3D10:
5464         case RENDERPATH_D3D11:
5465         case RENDERPATH_SOFT:
5466                 break;
5467         }
5468         GL_CullFace(GL_NONE);
5469 }
5470
5471 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5472 {
5473         DrawQ_Finish();
5474
5475         R_SetupView(true, fbo, depthtexture, colortexture);
5476         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5477         GL_Color(1, 1, 1, 1);
5478         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5479         GL_BlendFunc(GL_ONE, GL_ZERO);
5480         GL_ScissorTest(true);
5481         GL_DepthMask(true);
5482         GL_DepthRange(0, 1);
5483         GL_DepthTest(true);
5484         GL_DepthFunc(GL_LEQUAL);
5485         R_EntityMatrix(&identitymatrix);
5486         R_Mesh_ResetTextureState();
5487         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5488         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5489         switch(vid.renderpath)
5490         {
5491         case RENDERPATH_GL11:
5492         case RENDERPATH_GL13:
5493         case RENDERPATH_GL20:
5494         case RENDERPATH_GLES1:
5495         case RENDERPATH_GLES2:
5496                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5497                 break;
5498         case RENDERPATH_D3D9:
5499         case RENDERPATH_D3D10:
5500         case RENDERPATH_D3D11:
5501         case RENDERPATH_SOFT:
5502                 break;
5503         }
5504         GL_CullFace(r_refdef.view.cullface_back);
5505 }
5506
5507 /*
5508 ================
5509 R_RenderView_UpdateViewVectors
5510 ================
5511 */
5512 static void R_RenderView_UpdateViewVectors(void)
5513 {
5514         // break apart the view matrix into vectors for various purposes
5515         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5516         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5517         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5518         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5519         // make an inverted copy of the view matrix for tracking sprites
5520         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5521 }
5522
5523 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5524 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5525
5526 static void R_Water_StartFrame(void)
5527 {
5528         int i;
5529         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5530         r_waterstate_waterplane_t *p;
5531         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5532
5533         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5534                 return;
5535
5536         switch(vid.renderpath)
5537         {
5538         case RENDERPATH_GL20:
5539         case RENDERPATH_D3D9:
5540         case RENDERPATH_D3D10:
5541         case RENDERPATH_D3D11:
5542         case RENDERPATH_SOFT:
5543         case RENDERPATH_GLES2:
5544                 break;
5545         case RENDERPATH_GL11:
5546         case RENDERPATH_GL13:
5547         case RENDERPATH_GLES1:
5548                 return;
5549         }
5550
5551         // set waterwidth and waterheight to the water resolution that will be
5552         // used (often less than the screen resolution for faster rendering)
5553         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5554
5555         // calculate desired texture sizes
5556         // can't use water if the card does not support the texture size
5557         if (!r_water.integer || r_showsurfaces.integer)
5558                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5559         else if (vid.support.arb_texture_non_power_of_two)
5560         {
5561                 texturewidth = waterwidth;
5562                 textureheight = waterheight;
5563                 camerawidth = waterwidth;
5564                 cameraheight = waterheight;
5565         }
5566         else
5567         {
5568                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5569                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5570                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5571                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5572         }
5573
5574         // allocate textures as needed
5575         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))
5576         {
5577                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5578                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5579                 {
5580                         if (p->texture_refraction)
5581                                 R_FreeTexture(p->texture_refraction);
5582                         p->texture_refraction = NULL;
5583                         if (p->fbo_refraction)
5584                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5585                         p->fbo_refraction = 0;
5586                         if (p->texture_reflection)
5587                                 R_FreeTexture(p->texture_reflection);
5588                         p->texture_reflection = NULL;
5589                         if (p->fbo_reflection)
5590                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5591                         p->fbo_reflection = 0;
5592                         if (p->texture_camera)
5593                                 R_FreeTexture(p->texture_camera);
5594                         p->texture_camera = NULL;
5595                         if (p->fbo_camera)
5596                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5597                         p->fbo_camera = 0;
5598                 }
5599                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5600                 r_fb.water.texturewidth = texturewidth;
5601                 r_fb.water.textureheight = textureheight;
5602                 r_fb.water.camerawidth = camerawidth;
5603                 r_fb.water.cameraheight = cameraheight;
5604         }
5605
5606         if (r_fb.water.texturewidth)
5607         {
5608                 int scaledwidth, scaledheight;
5609
5610                 r_fb.water.enabled = true;
5611
5612                 // water resolution is usually reduced
5613                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5614                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5615                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5616
5617                 // set up variables that will be used in shader setup
5618                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5619                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5620                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5621                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5622         }
5623
5624         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5625         r_fb.water.numwaterplanes = 0;
5626 }
5627
5628 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5629 {
5630         int planeindex, bestplaneindex, vertexindex;
5631         vec3_t mins, maxs, normal, center, v, n;
5632         vec_t planescore, bestplanescore;
5633         mplane_t plane;
5634         r_waterstate_waterplane_t *p;
5635         texture_t *t = R_GetCurrentTexture(surface->texture);
5636
5637         rsurface.texture = t;
5638         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5639         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5640         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5641                 return;
5642         // average the vertex normals, find the surface bounds (after deformvertexes)
5643         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5644         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5645         VectorCopy(n, normal);
5646         VectorCopy(v, mins);
5647         VectorCopy(v, maxs);
5648         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5649         {
5650                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5651                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5652                 VectorAdd(normal, n, normal);
5653                 mins[0] = min(mins[0], v[0]);
5654                 mins[1] = min(mins[1], v[1]);
5655                 mins[2] = min(mins[2], v[2]);
5656                 maxs[0] = max(maxs[0], v[0]);
5657                 maxs[1] = max(maxs[1], v[1]);
5658                 maxs[2] = max(maxs[2], v[2]);
5659         }
5660         VectorNormalize(normal);
5661         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5662
5663         VectorCopy(normal, plane.normal);
5664         VectorNormalize(plane.normal);
5665         plane.dist = DotProduct(center, plane.normal);
5666         PlaneClassify(&plane);
5667         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5668         {
5669                 // skip backfaces (except if nocullface is set)
5670 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5671 //                      return;
5672                 VectorNegate(plane.normal, plane.normal);
5673                 plane.dist *= -1;
5674                 PlaneClassify(&plane);
5675         }
5676
5677
5678         // find a matching plane if there is one
5679         bestplaneindex = -1;
5680         bestplanescore = 1048576.0f;
5681         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5682         {
5683                 if(p->camera_entity == t->camera_entity)
5684                 {
5685                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5686                         if (bestplaneindex < 0 || bestplanescore > planescore)
5687                         {
5688                                 bestplaneindex = planeindex;
5689                                 bestplanescore = planescore;
5690                         }
5691                 }
5692         }
5693         planeindex = bestplaneindex;
5694         p = r_fb.water.waterplanes + planeindex;
5695
5696         // if this surface does not fit any known plane rendered this frame, add one
5697         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5698         {
5699                 // store the new plane
5700                 planeindex = r_fb.water.numwaterplanes++;
5701                 p = r_fb.water.waterplanes + planeindex;
5702                 p->plane = plane;
5703                 // clear materialflags and pvs
5704                 p->materialflags = 0;
5705                 p->pvsvalid = false;
5706                 p->camera_entity = t->camera_entity;
5707                 VectorCopy(mins, p->mins);
5708                 VectorCopy(maxs, p->maxs);
5709         }
5710         else
5711         {
5712                 // merge mins/maxs when we're adding this surface to the plane
5713                 p->mins[0] = min(p->mins[0], mins[0]);
5714                 p->mins[1] = min(p->mins[1], mins[1]);
5715                 p->mins[2] = min(p->mins[2], mins[2]);
5716                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5717                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5718                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5719         }
5720         // merge this surface's materialflags into the waterplane
5721         p->materialflags |= t->currentmaterialflags;
5722         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5723         {
5724                 // merge this surface's PVS into the waterplane
5725                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5726                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5727                 {
5728                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5729                         p->pvsvalid = true;
5730                 }
5731         }
5732 }
5733
5734 extern cvar_t r_drawparticles;
5735 extern cvar_t r_drawdecals;
5736
5737 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5738 {
5739         int myscissor[4];
5740         r_refdef_view_t originalview;
5741         r_refdef_view_t myview;
5742         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;
5743         r_waterstate_waterplane_t *p;
5744         vec3_t visorigin;
5745         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5746
5747         originalview = r_refdef.view;
5748
5749         // lowquality hack, temporarily shut down some cvars and restore afterwards
5750         qualityreduction = r_water_lowquality.integer;
5751         if (qualityreduction > 0)
5752         {
5753                 if (qualityreduction >= 1)
5754                 {
5755                         old_r_shadows = r_shadows.integer;
5756                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5757                         old_r_dlight = r_shadow_realtime_dlight.integer;
5758                         Cvar_SetValueQuick(&r_shadows, 0);
5759                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5760                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5761                 }
5762                 if (qualityreduction >= 2)
5763                 {
5764                         old_r_dynamic = r_dynamic.integer;
5765                         old_r_particles = r_drawparticles.integer;
5766                         old_r_decals = r_drawdecals.integer;
5767                         Cvar_SetValueQuick(&r_dynamic, 0);
5768                         Cvar_SetValueQuick(&r_drawparticles, 0);
5769                         Cvar_SetValueQuick(&r_drawdecals, 0);
5770                 }
5771         }
5772
5773         // make sure enough textures are allocated
5774         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5775         {
5776                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5777                 {
5778                         if (!p->texture_refraction)
5779                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5780                         if (!p->texture_refraction)
5781                                 goto error;
5782                         if (usewaterfbo)
5783                         {
5784                                 if (r_fb.water.depthtexture == NULL)
5785                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
5786                                 if (p->fbo_refraction == 0)
5787                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5788                         }
5789                 }
5790                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5791                 {
5792                         if (!p->texture_camera)
5793                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5794                         if (!p->texture_camera)
5795                                 goto error;
5796                         if (usewaterfbo)
5797                         {
5798                                 if (r_fb.water.depthtexture == NULL)
5799                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
5800                                 if (p->fbo_camera == 0)
5801                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5802                         }
5803                 }
5804
5805                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5806                 {
5807                         if (!p->texture_reflection)
5808                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5809                         if (!p->texture_reflection)
5810                                 goto error;
5811                         if (usewaterfbo)
5812                         {
5813                                 if (r_fb.water.depthtexture == NULL)
5814                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
5815                                 if (p->fbo_reflection == 0)
5816                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5817                         }
5818                 }
5819         }
5820
5821         // render views
5822         r_refdef.view = originalview;
5823         r_refdef.view.showdebug = false;
5824         r_refdef.view.width = r_fb.water.waterwidth;
5825         r_refdef.view.height = r_fb.water.waterheight;
5826         r_refdef.view.useclipplane = true;
5827         myview = r_refdef.view;
5828         r_fb.water.renderingscene = true;
5829         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5830         {
5831                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5832                 {
5833                         r_refdef.view = myview;
5834                         if(r_water_scissormode.integer)
5835                         {
5836                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5837                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5838                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5839                         }
5840
5841                         // render reflected scene and copy into texture
5842                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5843                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5844                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5845                         r_refdef.view.clipplane = p->plane;
5846                         // reverse the cullface settings for this render
5847                         r_refdef.view.cullface_front = GL_FRONT;
5848                         r_refdef.view.cullface_back = GL_BACK;
5849                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5850                         {
5851                                 r_refdef.view.usecustompvs = true;
5852                                 if (p->pvsvalid)
5853                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5854                                 else
5855                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5856                         }
5857
5858                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5859                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5860                         R_ClearScreen(r_refdef.fogenabled);
5861                         if(r_water_scissormode.integer & 2)
5862                                 R_View_UpdateWithScissor(myscissor);
5863                         else
5864                                 R_View_Update();
5865                         if(r_water_scissormode.integer & 1)
5866                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5867                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5868
5869                         if (!p->fbo_reflection)
5870                                 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);
5871                         r_fb.water.hideplayer = false;
5872                 }
5873
5874                 // render the normal view scene and copy into texture
5875                 // (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)
5876                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5877                 {
5878                         r_refdef.view = myview;
5879                         if(r_water_scissormode.integer)
5880                         {
5881                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5882                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5883                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5884                         }
5885
5886                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5887
5888                         r_refdef.view.clipplane = p->plane;
5889                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5890                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5891
5892                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5893                         {
5894                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5895                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5896                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5897                                 R_RenderView_UpdateViewVectors();
5898                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5899                                 {
5900                                         r_refdef.view.usecustompvs = true;
5901                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5902                                 }
5903                         }
5904
5905                         PlaneClassify(&r_refdef.view.clipplane);
5906
5907                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5908                         R_ClearScreen(r_refdef.fogenabled);
5909                         if(r_water_scissormode.integer & 2)
5910                                 R_View_UpdateWithScissor(myscissor);
5911                         else
5912                                 R_View_Update();
5913                         if(r_water_scissormode.integer & 1)
5914                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5915                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5916
5917                         if (!p->fbo_refraction)
5918                                 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);
5919                         r_fb.water.hideplayer = false;
5920                 }
5921                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5922                 {
5923                         r_refdef.view = myview;
5924
5925                         r_refdef.view.clipplane = p->plane;
5926                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5927                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5928
5929                         r_refdef.view.width = r_fb.water.camerawidth;
5930                         r_refdef.view.height = r_fb.water.cameraheight;
5931                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5932                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5933                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5934                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5935
5936                         if(p->camera_entity)
5937                         {
5938                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5939                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5940                         }
5941
5942                         // note: all of the view is used for displaying... so
5943                         // there is no use in scissoring
5944
5945                         // reverse the cullface settings for this render
5946                         r_refdef.view.cullface_front = GL_FRONT;
5947                         r_refdef.view.cullface_back = GL_BACK;
5948                         // also reverse the view matrix
5949                         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
5950                         R_RenderView_UpdateViewVectors();
5951                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5952                         {
5953                                 r_refdef.view.usecustompvs = true;
5954                                 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);
5955                         }
5956                         
5957                         // camera needs no clipplane
5958                         r_refdef.view.useclipplane = false;
5959
5960                         PlaneClassify(&r_refdef.view.clipplane);
5961
5962                         r_fb.water.hideplayer = false;
5963
5964                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5965                         R_ClearScreen(r_refdef.fogenabled);
5966                         R_View_Update();
5967                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5968
5969                         if (!p->fbo_camera)
5970                                 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);
5971                         r_fb.water.hideplayer = false;
5972                 }
5973
5974         }
5975         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5976         r_fb.water.renderingscene = false;
5977         r_refdef.view = originalview;
5978         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5979         if (!r_fb.water.depthtexture)
5980                 R_ClearScreen(r_refdef.fogenabled);
5981         R_View_Update();
5982         goto finish;
5983 error:
5984         r_refdef.view = originalview;
5985         r_fb.water.renderingscene = false;
5986         Cvar_SetValueQuick(&r_water, 0);
5987         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5988 finish:
5989         // lowquality hack, restore cvars
5990         if (qualityreduction > 0)
5991         {
5992                 if (qualityreduction >= 1)
5993                 {
5994                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5995                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5996                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5997                 }
5998                 if (qualityreduction >= 2)
5999                 {
6000                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6001                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6002                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6003                 }
6004         }
6005 }
6006
6007 void R_Bloom_StartFrame(void)
6008 {
6009         int i;
6010         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6011         int viewwidth, viewheight;
6012         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
6013         textype_t textype = TEXTYPE_COLORBUFFER;
6014
6015         switch (vid.renderpath)
6016         {
6017         case RENDERPATH_GL20:
6018         case RENDERPATH_GLES2:
6019                 if (vid.support.ext_framebuffer_object)
6020                 {
6021                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6022                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6023                 }
6024                 break;
6025         case RENDERPATH_GL11:
6026         case RENDERPATH_GL13:
6027         case RENDERPATH_GLES1:
6028         case RENDERPATH_D3D9:
6029         case RENDERPATH_D3D10:
6030         case RENDERPATH_D3D11:
6031         case RENDERPATH_SOFT:
6032                 break;
6033         }
6034
6035         if (r_viewscale_fpsscaling.integer)
6036         {
6037                 double actualframetime;
6038                 double targetframetime;
6039                 double adjust;
6040                 actualframetime = r_refdef.lastdrawscreentime;
6041                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6042                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6043                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6044                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6045                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6046                 viewscalefpsadjusted += adjust;
6047                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6048         }
6049         else
6050                 viewscalefpsadjusted = 1.0f;
6051
6052         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6053
6054         switch(vid.renderpath)
6055         {
6056         case RENDERPATH_GL20:
6057         case RENDERPATH_D3D9:
6058         case RENDERPATH_D3D10:
6059         case RENDERPATH_D3D11:
6060         case RENDERPATH_SOFT:
6061         case RENDERPATH_GLES2:
6062                 break;
6063         case RENDERPATH_GL11:
6064         case RENDERPATH_GL13:
6065         case RENDERPATH_GLES1:
6066                 return;
6067         }
6068
6069         // set bloomwidth and bloomheight to the bloom resolution that will be
6070         // used (often less than the screen resolution for faster rendering)
6071         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6072         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6073         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6074         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6075         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6076
6077         // calculate desired texture sizes
6078         if (vid.support.arb_texture_non_power_of_two)
6079         {
6080                 screentexturewidth = vid.width;
6081                 screentextureheight = vid.height;
6082                 bloomtexturewidth = r_fb.bloomwidth;
6083                 bloomtextureheight = r_fb.bloomheight;
6084         }
6085         else
6086         {
6087                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6088                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6089                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6090                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6091         }
6092
6093         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))
6094         {
6095                 Cvar_SetValueQuick(&r_bloom, 0);
6096                 Cvar_SetValueQuick(&r_motionblur, 0);
6097                 Cvar_SetValueQuick(&r_damageblur, 0);
6098         }
6099
6100         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6101          && !r_bloom.integer
6102          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6103          && !useviewfbo
6104          && r_viewscale.value == 1.0f
6105          && !r_viewscale_fpsscaling.integer)
6106                 screentexturewidth = screentextureheight = 0;
6107         if (!r_bloom.integer)
6108                 bloomtexturewidth = bloomtextureheight = 0;
6109
6110         // allocate textures as needed
6111         if (r_fb.screentexturewidth != screentexturewidth
6112          || r_fb.screentextureheight != screentextureheight
6113          || r_fb.bloomtexturewidth != bloomtexturewidth
6114          || r_fb.bloomtextureheight != bloomtextureheight
6115          || r_fb.textype != textype
6116          || useviewfbo != (r_fb.fbo != 0))
6117         {
6118                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6119                 {
6120                         if (r_fb.bloomtexture[i])
6121                                 R_FreeTexture(r_fb.bloomtexture[i]);
6122                         r_fb.bloomtexture[i] = NULL;
6123
6124                         if (r_fb.bloomfbo[i])
6125                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6126                         r_fb.bloomfbo[i] = 0;
6127                 }
6128
6129                 if (r_fb.fbo)
6130                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6131                 r_fb.fbo = 0;
6132
6133                 if (r_fb.colortexture)
6134                         R_FreeTexture(r_fb.colortexture);
6135                 r_fb.colortexture = NULL;
6136
6137                 if (r_fb.depthtexture)
6138                         R_FreeTexture(r_fb.depthtexture);
6139                 r_fb.depthtexture = NULL;
6140
6141                 if (r_fb.ghosttexture)
6142                         R_FreeTexture(r_fb.ghosttexture);
6143                 r_fb.ghosttexture = NULL;
6144
6145                 r_fb.screentexturewidth = screentexturewidth;
6146                 r_fb.screentextureheight = screentextureheight;
6147                 r_fb.bloomtexturewidth = bloomtexturewidth;
6148                 r_fb.bloomtextureheight = bloomtextureheight;
6149                 r_fb.textype = textype;
6150
6151                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6152                 {
6153                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6154                                 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);
6155                         r_fb.ghosttexture_valid = false;
6156                         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);
6157                         if (useviewfbo)
6158                         {
6159                                 // FIXME: choose depth bits based on a cvar
6160                                 r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false, vid.support.ext_packed_depth_stencil);
6161                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6162                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6163 #ifndef USE_GLES2
6164                                 // render depth into one texture and color into the other
6165                                 if (qglDrawBuffer)
6166                                 {
6167                                         int status;
6168                                         qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6169                                         qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6170                                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6171                                         if (status != GL_FRAMEBUFFER_COMPLETE)
6172                                                 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6173                                 }
6174 #endif
6175                         }
6176                 }
6177
6178                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6179                 {
6180                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6181                         {
6182                                 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);
6183                                 if (useviewfbo)
6184                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6185                         }
6186                 }
6187         }
6188
6189         // bloom texture is a different resolution
6190         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6191         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6192         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6193         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6194         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6195
6196         // set up a texcoord array for the full resolution screen image
6197         // (we have to keep this around to copy back during final render)
6198         r_fb.screentexcoord2f[0] = 0;
6199         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6200         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6201         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6202         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6203         r_fb.screentexcoord2f[5] = 0;
6204         r_fb.screentexcoord2f[6] = 0;
6205         r_fb.screentexcoord2f[7] = 0;
6206
6207         // set up a texcoord array for the reduced resolution bloom image
6208         // (which will be additive blended over the screen image)
6209         r_fb.bloomtexcoord2f[0] = 0;
6210         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6211         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6212         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6213         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6214         r_fb.bloomtexcoord2f[5] = 0;
6215         r_fb.bloomtexcoord2f[6] = 0;
6216         r_fb.bloomtexcoord2f[7] = 0;
6217
6218         switch(vid.renderpath)
6219         {
6220         case RENDERPATH_GL11:
6221         case RENDERPATH_GL13:
6222         case RENDERPATH_GL20:
6223         case RENDERPATH_SOFT:
6224         case RENDERPATH_GLES1:
6225         case RENDERPATH_GLES2:
6226                 break;
6227         case RENDERPATH_D3D9:
6228         case RENDERPATH_D3D10:
6229         case RENDERPATH_D3D11:
6230                 {
6231                         int i;
6232                         for (i = 0;i < 4;i++)
6233                         {
6234                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6235                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6236                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6237                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6238                         }
6239                 }
6240                 break;
6241         }
6242
6243         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);
6244
6245         if (r_fb.fbo)
6246                 r_refdef.view.clear = true;
6247 }
6248
6249 void R_Bloom_MakeTexture(void)
6250 {
6251         int x, range, dir;
6252         float xoffset, yoffset, r, brighten;
6253         rtexture_t *intex;
6254         float colorscale = r_bloom_colorscale.value;
6255
6256         r_refdef.stats.bloom++;
6257
6258         if (!r_fb.fbo)
6259         {
6260                 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);
6261                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6262         }
6263
6264         // scale down screen texture to the bloom texture size
6265         CHECKGLERROR
6266         r_fb.bloomindex = 0;
6267         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6268         R_SetViewport(&r_fb.bloomviewport);
6269         GL_BlendFunc(GL_ONE, GL_ZERO);
6270         GL_Color(colorscale, colorscale, colorscale, 1);
6271         // 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...
6272         switch(vid.renderpath)
6273         {
6274         case RENDERPATH_GL11:
6275         case RENDERPATH_GL13:
6276         case RENDERPATH_GL20:
6277         case RENDERPATH_GLES1:
6278         case RENDERPATH_GLES2:
6279         case RENDERPATH_SOFT:
6280                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6281                 break;
6282         case RENDERPATH_D3D9:
6283         case RENDERPATH_D3D10:
6284         case RENDERPATH_D3D11:
6285                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6286                 break;
6287         }
6288         // TODO: do boxfilter scale-down in shader?
6289         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6290         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6291         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6292
6293         // we now have a properly scaled bloom image
6294         if (!r_fb.bloomfbo[r_fb.bloomindex])
6295         {
6296                 // copy it into the bloom texture
6297                 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);
6298                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6299         }
6300
6301         // multiply bloom image by itself as many times as desired
6302         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6303         {
6304                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6305                 r_fb.bloomindex ^= 1;
6306                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6307                 x *= 2;
6308                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6309                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6310                 GL_Color(r,r,r,1);
6311                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6312                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6313                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6314                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6315
6316                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6317                 {
6318                         // copy the darkened image to a texture
6319                         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);
6320                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6321                 }
6322         }
6323
6324         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6325         brighten = r_bloom_brighten.value;
6326         brighten = sqrt(brighten);
6327         if(range >= 1)
6328                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6329
6330         for (dir = 0;dir < 2;dir++)
6331         {
6332                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6333                 r_fb.bloomindex ^= 1;
6334                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6335                 // blend on at multiple vertical offsets to achieve a vertical blur
6336                 // TODO: do offset blends using GLSL
6337                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6338                 GL_BlendFunc(GL_ONE, GL_ZERO);
6339                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6340                 for (x = -range;x <= range;x++)
6341                 {
6342                         if (!dir){xoffset = 0;yoffset = x;}
6343                         else {xoffset = x;yoffset = 0;}
6344                         xoffset /= (float)r_fb.bloomtexturewidth;
6345                         yoffset /= (float)r_fb.bloomtextureheight;
6346                         // compute a texcoord array with the specified x and y offset
6347                         r_fb.offsettexcoord2f[0] = xoffset+0;
6348                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6349                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6350                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6351                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6352                         r_fb.offsettexcoord2f[5] = yoffset+0;
6353                         r_fb.offsettexcoord2f[6] = xoffset+0;
6354                         r_fb.offsettexcoord2f[7] = yoffset+0;
6355                         // this r value looks like a 'dot' particle, fading sharply to
6356                         // black at the edges
6357                         // (probably not realistic but looks good enough)
6358                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6359                         //r = brighten/(range*2+1);
6360                         r = brighten / (range * 2 + 1);
6361                         if(range >= 1)
6362                                 r *= (1 - x*x/(float)(range*range));
6363                         GL_Color(r, r, r, 1);
6364                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6365                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6366                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6367                         GL_BlendFunc(GL_ONE, GL_ONE);
6368                 }
6369
6370                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6371                 {
6372                         // copy the vertically or horizontally blurred bloom view to a texture
6373                         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);
6374                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6375                 }
6376         }
6377 }
6378
6379 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6380 {
6381         unsigned int permutation;
6382         float uservecs[4][4];
6383
6384         switch (vid.renderpath)
6385         {
6386         case RENDERPATH_GL20:
6387         case RENDERPATH_D3D9:
6388         case RENDERPATH_D3D10:
6389         case RENDERPATH_D3D11:
6390         case RENDERPATH_SOFT:
6391         case RENDERPATH_GLES2:
6392                 permutation =
6393                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6394                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6395                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6396                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6397                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6398
6399                 if (r_fb.colortexture)
6400                 {
6401                         if (!r_fb.fbo)
6402                         {
6403                                 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);
6404                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6405                         }
6406
6407                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6408                         {
6409                                 // declare variables
6410                                 float blur_factor, blur_mouseaccel, blur_velocity;
6411                                 static float blur_average; 
6412                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6413
6414                                 // set a goal for the factoring
6415                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6416                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6417                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6418                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6419                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6420                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6421
6422                                 // from the goal, pick an averaged value between goal and last value
6423                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6424                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6425
6426                                 // enforce minimum amount of blur 
6427                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6428
6429                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6430
6431                                 // calculate values into a standard alpha
6432                                 cl.motionbluralpha = 1 - exp(-
6433                                                 (
6434                                                  (r_motionblur.value * blur_factor / 80)
6435                                                  +
6436                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6437                                                 )
6438                                                 /
6439                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6440                                           );
6441
6442                                 // randomization for the blur value to combat persistent ghosting
6443                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6444                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6445
6446                                 // apply the blur
6447                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6448                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6449                                 {
6450                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6451                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6452                                         switch(vid.renderpath)
6453                                         {
6454                                         case RENDERPATH_GL11:
6455                                         case RENDERPATH_GL13:
6456                                         case RENDERPATH_GL20:
6457                                         case RENDERPATH_GLES1:
6458                                         case RENDERPATH_GLES2:
6459                                         case RENDERPATH_SOFT:
6460                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6461                                                 break;
6462                                         case RENDERPATH_D3D9:
6463                                         case RENDERPATH_D3D10:
6464                                         case RENDERPATH_D3D11:
6465                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6466                                                 break;
6467                                         }
6468                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6469                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6470                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6471                                 }
6472
6473                                 // updates old view angles for next pass
6474                                 VectorCopy(cl.viewangles, blur_oldangles);
6475
6476                                 // copy view into the ghost texture
6477                                 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);
6478                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6479                                 r_fb.ghosttexture_valid = true;
6480                         }
6481                 }
6482                 else
6483                 {
6484                         // no r_fb.colortexture means we're rendering to the real fb
6485                         // we may still have to do view tint...
6486                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6487                         {
6488                                 // apply a color tint to the whole view
6489                                 R_ResetViewRendering2D(0, NULL, NULL);
6490                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6491                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6492                                 R_SetupShader_Generic_NoTexture(false, true);
6493                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6494                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6495                         }
6496                         break; // no screen processing, no bloom, skip it
6497                 }
6498
6499                 if (r_fb.bloomtexture[0])
6500                 {
6501                         // make the bloom texture
6502                         R_Bloom_MakeTexture();
6503                 }
6504
6505 #if _MSC_VER >= 1400
6506 #define sscanf sscanf_s
6507 #endif
6508                 memset(uservecs, 0, sizeof(uservecs));
6509                 if (r_glsl_postprocess_uservec1_enable.integer)
6510                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6511                 if (r_glsl_postprocess_uservec2_enable.integer)
6512                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6513                 if (r_glsl_postprocess_uservec3_enable.integer)
6514                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6515                 if (r_glsl_postprocess_uservec4_enable.integer)
6516                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6517
6518                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6519                 GL_Color(1, 1, 1, 1);
6520                 GL_BlendFunc(GL_ONE, GL_ZERO);
6521
6522                 switch(vid.renderpath)
6523                 {
6524                 case RENDERPATH_GL20:
6525                 case RENDERPATH_GLES2:
6526                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6527                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6528                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6529                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6530                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6531                         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]);
6532                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6533                         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]);
6534                         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]);
6535                         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]);
6536                         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]);
6537                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6538                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6539                         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);
6540                         break;
6541                 case RENDERPATH_D3D9:
6542 #ifdef SUPPORTD3D
6543                         // 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...
6544                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6545                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6546                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6547                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6548                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6549                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6550                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6551                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6552                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6553                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6554                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6555                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6556                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6557                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6558 #endif
6559                         break;
6560                 case RENDERPATH_D3D10:
6561                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6562                         break;
6563                 case RENDERPATH_D3D11:
6564                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6565                         break;
6566                 case RENDERPATH_SOFT:
6567                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6568                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6569                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6570                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6571                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6572                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6573                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6574                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6575                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6576                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6577                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6578                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6579                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6580                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6581                         break;
6582                 default:
6583                         break;
6584                 }
6585                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6586                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6587                 break;
6588         case RENDERPATH_GL11:
6589         case RENDERPATH_GL13:
6590         case RENDERPATH_GLES1:
6591                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6592                 {
6593                         // apply a color tint to the whole view
6594                         R_ResetViewRendering2D(0, NULL, NULL);
6595                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6596                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6597                         R_SetupShader_Generic_NoTexture(false, true);
6598                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6599                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6600                 }
6601                 break;
6602         }
6603 }
6604
6605 matrix4x4_t r_waterscrollmatrix;
6606
6607 void R_UpdateFog(void)
6608 {
6609         // Nehahra fog
6610         if (gamemode == GAME_NEHAHRA)
6611         {
6612                 if (gl_fogenable.integer)
6613                 {
6614                         r_refdef.oldgl_fogenable = true;
6615                         r_refdef.fog_density = gl_fogdensity.value;
6616                         r_refdef.fog_red = gl_fogred.value;
6617                         r_refdef.fog_green = gl_foggreen.value;
6618                         r_refdef.fog_blue = gl_fogblue.value;
6619                         r_refdef.fog_alpha = 1;
6620                         r_refdef.fog_start = 0;
6621                         r_refdef.fog_end = gl_skyclip.value;
6622                         r_refdef.fog_height = 1<<30;
6623                         r_refdef.fog_fadedepth = 128;
6624                 }
6625                 else if (r_refdef.oldgl_fogenable)
6626                 {
6627                         r_refdef.oldgl_fogenable = false;
6628                         r_refdef.fog_density = 0;
6629                         r_refdef.fog_red = 0;
6630                         r_refdef.fog_green = 0;
6631                         r_refdef.fog_blue = 0;
6632                         r_refdef.fog_alpha = 0;
6633                         r_refdef.fog_start = 0;
6634                         r_refdef.fog_end = 0;
6635                         r_refdef.fog_height = 1<<30;
6636                         r_refdef.fog_fadedepth = 128;
6637                 }
6638         }
6639
6640         // fog parms
6641         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6642         r_refdef.fog_start = max(0, r_refdef.fog_start);
6643         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6644
6645         if (r_refdef.fog_density && r_drawfog.integer)
6646         {
6647                 r_refdef.fogenabled = true;
6648                 // this is the point where the fog reaches 0.9986 alpha, which we
6649                 // consider a good enough cutoff point for the texture
6650                 // (0.9986 * 256 == 255.6)
6651                 if (r_fog_exp2.integer)
6652                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6653                 else
6654                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6655                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6656                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6657                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6658                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6659                         R_BuildFogHeightTexture();
6660                 // fog color was already set
6661                 // update the fog texture
6662                 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)
6663                         R_BuildFogTexture();
6664                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6665                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6666         }
6667         else
6668                 r_refdef.fogenabled = false;
6669
6670         // fog color
6671         if (r_refdef.fog_density)
6672         {
6673                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6674                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6675                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6676
6677                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6678                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6679                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6680                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6681
6682                 {
6683                         vec3_t fogvec;
6684                         VectorCopy(r_refdef.fogcolor, fogvec);
6685                         //   color.rgb *= ContrastBoost * SceneBrightness;
6686                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6687                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6688                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6689                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6690                 }
6691         }
6692 }
6693
6694 void R_UpdateVariables(void)
6695 {
6696         R_Textures_Frame();
6697
6698         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6699
6700         r_refdef.farclip = r_farclip_base.value;
6701         if (r_refdef.scene.worldmodel)
6702                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6703         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6704
6705         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6706                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6707         r_refdef.polygonfactor = 0;
6708         r_refdef.polygonoffset = 0;
6709         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6710         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6711
6712         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6713         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6714         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6715         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6716         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6717         if (FAKELIGHT_ENABLED)
6718         {
6719                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6720         }
6721         if (r_showsurfaces.integer)
6722         {
6723                 r_refdef.scene.rtworld = false;
6724                 r_refdef.scene.rtworldshadows = false;
6725                 r_refdef.scene.rtdlight = false;
6726                 r_refdef.scene.rtdlightshadows = false;
6727                 r_refdef.lightmapintensity = 0;
6728         }
6729
6730         switch(vid.renderpath)
6731         {
6732         case RENDERPATH_GL20:
6733         case RENDERPATH_D3D9:
6734         case RENDERPATH_D3D10:
6735         case RENDERPATH_D3D11:
6736         case RENDERPATH_SOFT:
6737         case RENDERPATH_GLES2:
6738                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6739                 {
6740                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6741                         {
6742                                 // build GLSL gamma texture
6743 #define RAMPWIDTH 256
6744                                 unsigned short ramp[RAMPWIDTH * 3];
6745                                 unsigned char rampbgr[RAMPWIDTH][4];
6746                                 int i;
6747
6748                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6749
6750                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6751                                 for(i = 0; i < RAMPWIDTH; ++i)
6752                                 {
6753                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6754                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6755                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6756                                         rampbgr[i][3] = 0;
6757                                 }
6758                                 if (r_texture_gammaramps)
6759                                 {
6760                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6761                                 }
6762                                 else
6763                                 {
6764                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6765                                 }
6766                         }
6767                 }
6768                 else
6769                 {
6770                         // remove GLSL gamma texture
6771                 }
6772                 break;
6773         case RENDERPATH_GL11:
6774         case RENDERPATH_GL13:
6775         case RENDERPATH_GLES1:
6776                 break;
6777         }
6778 }
6779
6780 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6781 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6782 /*
6783 ================
6784 R_SelectScene
6785 ================
6786 */
6787 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6788         if( scenetype != r_currentscenetype ) {
6789                 // store the old scenetype
6790                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6791                 r_currentscenetype = scenetype;
6792                 // move in the new scene
6793                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6794         }
6795 }
6796
6797 /*
6798 ================
6799 R_GetScenePointer
6800 ================
6801 */
6802 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6803 {
6804         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6805         if( scenetype == r_currentscenetype ) {
6806                 return &r_refdef.scene;
6807         } else {
6808                 return &r_scenes_store[ scenetype ];
6809         }
6810 }
6811
6812 int R_SortEntities_Compare(const void *ap, const void *bp)
6813 {
6814         const entity_render_t *a = *(const entity_render_t **)ap;
6815         const entity_render_t *b = *(const entity_render_t **)bp;
6816
6817         // 1. compare model
6818         if(a->model < b->model)
6819                 return -1;
6820         if(a->model > b->model)
6821                 return +1;
6822
6823         // 2. compare skin
6824         // TODO possibly calculate the REAL skinnum here first using
6825         // skinscenes?
6826         if(a->skinnum < b->skinnum)
6827                 return -1;
6828         if(a->skinnum > b->skinnum)
6829                 return +1;
6830
6831         // everything we compared is equal
6832         return 0;
6833 }
6834 void R_SortEntities(void)
6835 {
6836         // below or equal 2 ents, sorting never gains anything
6837         if(r_refdef.scene.numentities <= 2)
6838                 return;
6839         // sort
6840         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6841 }
6842
6843 /*
6844 ================
6845 R_RenderView
6846 ================
6847 */
6848 int dpsoftrast_test;
6849 extern void R_Shadow_UpdateBounceGridTexture(void);
6850 extern cvar_t r_shadow_bouncegrid;
6851 void R_RenderView(void)
6852 {
6853         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6854         int fbo;
6855         rtexture_t *depthtexture;
6856         rtexture_t *colortexture;
6857
6858         dpsoftrast_test = r_test.integer;
6859
6860         if (r_timereport_active)
6861                 R_TimeReport("start");
6862         r_textureframe++; // used only by R_GetCurrentTexture
6863         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6864
6865         if(R_CompileShader_CheckStaticParms())
6866                 R_GLSL_Restart_f();
6867
6868         if (!r_drawentities.integer)
6869                 r_refdef.scene.numentities = 0;
6870         else if (r_sortentities.integer)
6871                 R_SortEntities();
6872
6873         R_AnimCache_ClearCache();
6874         R_FrameData_NewFrame();
6875
6876         /* adjust for stereo display */
6877         if(R_Stereo_Active())
6878         {
6879                 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);
6880                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6881         }
6882
6883         if (r_refdef.view.isoverlay)
6884         {
6885                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6886                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6887                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6888                 R_TimeReport("depthclear");
6889
6890                 r_refdef.view.showdebug = false;
6891
6892                 r_fb.water.enabled = false;
6893                 r_fb.water.numwaterplanes = 0;
6894
6895                 R_RenderScene(0, NULL, NULL);
6896
6897                 r_refdef.view.matrix = originalmatrix;
6898
6899                 CHECKGLERROR
6900                 return;
6901         }
6902
6903         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6904         {
6905                 r_refdef.view.matrix = originalmatrix;
6906                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6907         }
6908
6909         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6910
6911         R_RenderView_UpdateViewVectors();
6912
6913         R_Shadow_UpdateWorldLightSelection();
6914
6915         R_Bloom_StartFrame();
6916         R_Water_StartFrame();
6917
6918         // now we probably have an fbo to render into
6919         fbo = r_fb.fbo;
6920         depthtexture = r_fb.depthtexture;
6921         colortexture = r_fb.colortexture;
6922
6923         CHECKGLERROR
6924         if (r_timereport_active)
6925                 R_TimeReport("viewsetup");
6926
6927         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6928
6929         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6930         {
6931                 R_ClearScreen(r_refdef.fogenabled);
6932                 if (r_timereport_active)
6933                         R_TimeReport("viewclear");
6934         }
6935         r_refdef.view.clear = true;
6936
6937         r_refdef.view.showdebug = true;
6938
6939         R_View_Update();
6940         if (r_timereport_active)
6941                 R_TimeReport("visibility");
6942
6943         R_Shadow_UpdateBounceGridTexture();
6944         if (r_timereport_active && r_shadow_bouncegrid.integer)
6945                 R_TimeReport("bouncegrid");
6946
6947         r_fb.water.numwaterplanes = 0;
6948         if (r_fb.water.enabled)
6949                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6950
6951         R_RenderScene(fbo, depthtexture, colortexture);
6952         r_fb.water.numwaterplanes = 0;
6953
6954         R_BlendView(fbo, depthtexture, colortexture);
6955         if (r_timereport_active)
6956                 R_TimeReport("blendview");
6957
6958         GL_Scissor(0, 0, vid.width, vid.height);
6959         GL_ScissorTest(false);
6960
6961         r_refdef.view.matrix = originalmatrix;
6962
6963         CHECKGLERROR
6964 }
6965
6966 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6967 {
6968         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6969         {
6970                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6971                 if (r_timereport_active)
6972                         R_TimeReport("waterworld");
6973         }
6974
6975         // don't let sound skip if going slow
6976         if (r_refdef.scene.extraupdate)
6977                 S_ExtraUpdate ();
6978
6979         R_DrawModelsAddWaterPlanes();
6980         if (r_timereport_active)
6981                 R_TimeReport("watermodels");
6982
6983         if (r_fb.water.numwaterplanes)
6984         {
6985                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6986                 if (r_timereport_active)
6987                         R_TimeReport("waterscenes");
6988         }
6989 }
6990
6991 extern void R_DrawLightningBeams (void);
6992 extern void VM_CL_AddPolygonsToMeshQueue (void);
6993 extern void R_DrawPortals (void);
6994 extern cvar_t cl_locs_show;
6995 static void R_DrawLocs(void);
6996 static void R_DrawEntityBBoxes(void);
6997 static void R_DrawModelDecals(void);
6998 extern cvar_t cl_decals_newsystem;
6999 extern qboolean r_shadow_usingdeferredprepass;
7000 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7001 {
7002         qboolean shadowmapping = false;
7003
7004         if (r_timereport_active)
7005                 R_TimeReport("beginscene");
7006
7007         r_refdef.stats.renders++;
7008
7009         R_UpdateFog();
7010
7011         // don't let sound skip if going slow
7012         if (r_refdef.scene.extraupdate)
7013                 S_ExtraUpdate ();
7014
7015         R_MeshQueue_BeginScene();
7016
7017         R_SkyStartFrame();
7018
7019         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);
7020
7021         if (r_timereport_active)
7022                 R_TimeReport("skystartframe");
7023
7024         if (cl.csqc_vidvars.drawworld)
7025         {
7026                 // don't let sound skip if going slow
7027                 if (r_refdef.scene.extraupdate)
7028                         S_ExtraUpdate ();
7029
7030                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7031                 {
7032                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7033                         if (r_timereport_active)
7034                                 R_TimeReport("worldsky");
7035                 }
7036
7037                 if (R_DrawBrushModelsSky() && r_timereport_active)
7038                         R_TimeReport("bmodelsky");
7039
7040                 if (skyrendermasked && skyrenderlater)
7041                 {
7042                         // we have to force off the water clipping plane while rendering sky
7043                         R_SetupView(false, fbo, depthtexture, colortexture);
7044                         R_Sky();
7045                         R_SetupView(true, fbo, depthtexture, colortexture);
7046                         if (r_timereport_active)
7047                                 R_TimeReport("sky");
7048                 }
7049         }
7050
7051         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7052         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7053                 R_Shadow_PrepareModelShadows();
7054         if (r_timereport_active)
7055                 R_TimeReport("preparelights");
7056
7057         if (R_Shadow_ShadowMappingEnabled())
7058                 shadowmapping = true;
7059
7060         if (r_shadow_usingdeferredprepass)
7061                 R_Shadow_DrawPrepass();
7062
7063         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7064         {
7065                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7066                 if (r_timereport_active)
7067                         R_TimeReport("worlddepth");
7068         }
7069         if (r_depthfirst.integer >= 2)
7070         {
7071                 R_DrawModelsDepth();
7072                 if (r_timereport_active)
7073                         R_TimeReport("modeldepth");
7074         }
7075
7076         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7077         {
7078                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7079                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7080                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7081                 // don't let sound skip if going slow
7082                 if (r_refdef.scene.extraupdate)
7083                         S_ExtraUpdate ();
7084         }
7085
7086         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7087         {
7088                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7089                 if (r_timereport_active)
7090                         R_TimeReport("world");
7091         }
7092
7093         // don't let sound skip if going slow
7094         if (r_refdef.scene.extraupdate)
7095                 S_ExtraUpdate ();
7096
7097         R_DrawModels();
7098         if (r_timereport_active)
7099                 R_TimeReport("models");
7100
7101         // don't let sound skip if going slow
7102         if (r_refdef.scene.extraupdate)
7103                 S_ExtraUpdate ();
7104
7105         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7106         {
7107                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7108                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7109                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7110                 // don't let sound skip if going slow
7111                 if (r_refdef.scene.extraupdate)
7112                         S_ExtraUpdate ();
7113         }
7114
7115         if (!r_shadow_usingdeferredprepass)
7116         {
7117                 R_Shadow_DrawLights();
7118                 if (r_timereport_active)
7119                         R_TimeReport("rtlights");
7120         }
7121
7122         // don't let sound skip if going slow
7123         if (r_refdef.scene.extraupdate)
7124                 S_ExtraUpdate ();
7125
7126         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7127         {
7128                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7129                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7130                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7131                 // don't let sound skip if going slow
7132                 if (r_refdef.scene.extraupdate)
7133                         S_ExtraUpdate ();
7134         }
7135
7136         if (cl.csqc_vidvars.drawworld)
7137         {
7138                 if (cl_decals_newsystem.integer)
7139                 {
7140                         R_DrawModelDecals();
7141                         if (r_timereport_active)
7142                                 R_TimeReport("modeldecals");
7143                 }
7144                 else
7145                 {
7146                         R_DrawDecals();
7147                         if (r_timereport_active)
7148                                 R_TimeReport("decals");
7149                 }
7150
7151                 R_DrawParticles();
7152                 if (r_timereport_active)
7153                         R_TimeReport("particles");
7154
7155                 R_DrawExplosions();
7156                 if (r_timereport_active)
7157                         R_TimeReport("explosions");
7158
7159                 R_DrawLightningBeams();
7160                 if (r_timereport_active)
7161                         R_TimeReport("lightning");
7162         }
7163
7164         VM_CL_AddPolygonsToMeshQueue();
7165
7166         if (r_refdef.view.showdebug)
7167         {
7168                 if (cl_locs_show.integer)
7169                 {
7170                         R_DrawLocs();
7171                         if (r_timereport_active)
7172                                 R_TimeReport("showlocs");
7173                 }
7174
7175                 if (r_drawportals.integer)
7176                 {
7177                         R_DrawPortals();
7178                         if (r_timereport_active)
7179                                 R_TimeReport("portals");
7180                 }
7181
7182                 if (r_showbboxes.value > 0)
7183                 {
7184                         R_DrawEntityBBoxes();
7185                         if (r_timereport_active)
7186                                 R_TimeReport("bboxes");
7187                 }
7188         }
7189
7190         if (r_transparent.integer)
7191         {
7192                 R_MeshQueue_RenderTransparent();
7193                 if (r_timereport_active)
7194                         R_TimeReport("drawtrans");
7195         }
7196
7197         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))
7198         {
7199                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7200                 if (r_timereport_active)
7201                         R_TimeReport("worlddebug");
7202                 R_DrawModelsDebug();
7203                 if (r_timereport_active)
7204                         R_TimeReport("modeldebug");
7205         }
7206
7207         if (cl.csqc_vidvars.drawworld)
7208         {
7209                 R_Shadow_DrawCoronas();
7210                 if (r_timereport_active)
7211                         R_TimeReport("coronas");
7212         }
7213
7214 #if 0
7215         {
7216                 GL_DepthTest(false);
7217                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7218                 GL_Color(1, 1, 1, 1);
7219                 qglBegin(GL_POLYGON);
7220                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7221                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7222                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7223                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7224                 qglEnd();
7225                 qglBegin(GL_POLYGON);
7226                 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]);
7227                 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]);
7228                 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]);
7229                 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]);
7230                 qglEnd();
7231                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7232         }
7233 #endif
7234
7235         // don't let sound skip if going slow
7236         if (r_refdef.scene.extraupdate)
7237                 S_ExtraUpdate ();
7238 }
7239
7240 static const unsigned short bboxelements[36] =
7241 {
7242         5, 1, 3, 5, 3, 7,
7243         6, 2, 0, 6, 0, 4,
7244         7, 3, 2, 7, 2, 6,
7245         4, 0, 1, 4, 1, 5,
7246         4, 5, 7, 4, 7, 6,
7247         1, 0, 2, 1, 2, 3,
7248 };
7249
7250 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7251 {
7252         int i;
7253         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7254
7255         RSurf_ActiveWorldEntity();
7256
7257         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7258         GL_DepthMask(false);
7259         GL_DepthRange(0, 1);
7260         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7261 //      R_Mesh_ResetTextureState();
7262
7263         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7264         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7265         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7266         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7267         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7268         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7269         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7270         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7271         R_FillColors(color4f, 8, cr, cg, cb, ca);
7272         if (r_refdef.fogenabled)
7273         {
7274                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7275                 {
7276                         f1 = RSurf_FogVertex(v);
7277                         f2 = 1 - f1;
7278                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7279                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7280                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7281                 }
7282         }
7283         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7284         R_Mesh_ResetTextureState();
7285         R_SetupShader_Generic_NoTexture(false, false);
7286         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7287 }
7288
7289 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7290 {
7291         int i;
7292         float color[4];
7293         prvm_edict_t *edict;
7294         prvm_prog_t *prog_save = prog;
7295
7296         // this function draws bounding boxes of server entities
7297         if (!sv.active)
7298                 return;
7299
7300         GL_CullFace(GL_NONE);
7301         R_SetupShader_Generic_NoTexture(false, false);
7302
7303         prog = 0;
7304         SV_VM_Begin();
7305         for (i = 0;i < numsurfaces;i++)
7306         {
7307                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7308                 switch ((int)PRVM_serveredictfloat(edict, solid))
7309                 {
7310                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7311                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7312                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7313                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7314                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7315                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7316                 }
7317                 color[3] *= r_showbboxes.value;
7318                 color[3] = bound(0, color[3], 1);
7319                 GL_DepthTest(!r_showdisabledepthtest.integer);
7320                 GL_CullFace(r_refdef.view.cullface_front);
7321                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7322         }
7323         SV_VM_End();
7324         prog = prog_save;
7325 }
7326
7327 static void R_DrawEntityBBoxes(void)
7328 {
7329         int i;
7330         prvm_edict_t *edict;
7331         vec3_t center;
7332         prvm_prog_t *prog_save = prog;
7333
7334         // this function draws bounding boxes of server entities
7335         if (!sv.active)
7336                 return;
7337
7338         prog = 0;
7339         SV_VM_Begin();
7340         for (i = 0;i < prog->num_edicts;i++)
7341         {
7342                 edict = PRVM_EDICT_NUM(i);
7343                 if (edict->priv.server->free)
7344                         continue;
7345                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7346                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7347                         continue;
7348                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7349                         continue;
7350                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7351                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7352         }
7353         SV_VM_End();
7354         prog = prog_save;
7355 }
7356
7357 static const int nomodelelement3i[24] =
7358 {
7359         5, 2, 0,
7360         5, 1, 2,
7361         5, 0, 3,
7362         5, 3, 1,
7363         0, 2, 4,
7364         2, 1, 4,
7365         3, 0, 4,
7366         1, 3, 4
7367 };
7368
7369 static const unsigned short nomodelelement3s[24] =
7370 {
7371         5, 2, 0,
7372         5, 1, 2,
7373         5, 0, 3,
7374         5, 3, 1,
7375         0, 2, 4,
7376         2, 1, 4,
7377         3, 0, 4,
7378         1, 3, 4
7379 };
7380
7381 static const float nomodelvertex3f[6*3] =
7382 {
7383         -16,   0,   0,
7384          16,   0,   0,
7385           0, -16,   0,
7386           0,  16,   0,
7387           0,   0, -16,
7388           0,   0,  16
7389 };
7390
7391 static const float nomodelcolor4f[6*4] =
7392 {
7393         0.0f, 0.0f, 0.5f, 1.0f,
7394         0.0f, 0.0f, 0.5f, 1.0f,
7395         0.0f, 0.5f, 0.0f, 1.0f,
7396         0.0f, 0.5f, 0.0f, 1.0f,
7397         0.5f, 0.0f, 0.0f, 1.0f,
7398         0.5f, 0.0f, 0.0f, 1.0f
7399 };
7400
7401 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7402 {
7403         int i;
7404         float f1, f2, *c;
7405         float color4f[6*4];
7406
7407         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);
7408
7409         // this is only called once per entity so numsurfaces is always 1, and
7410         // surfacelist is always {0}, so this code does not handle batches
7411
7412         if (rsurface.ent_flags & RENDER_ADDITIVE)
7413         {
7414                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7415                 GL_DepthMask(false);
7416         }
7417         else if (rsurface.colormod[3] < 1)
7418         {
7419                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7420                 GL_DepthMask(false);
7421         }
7422         else
7423         {
7424                 GL_BlendFunc(GL_ONE, GL_ZERO);
7425                 GL_DepthMask(true);
7426         }
7427         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7428         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7429         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7430         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7431         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7432         for (i = 0, c = color4f;i < 6;i++, c += 4)
7433         {
7434                 c[0] *= rsurface.colormod[0];
7435                 c[1] *= rsurface.colormod[1];
7436                 c[2] *= rsurface.colormod[2];
7437                 c[3] *= rsurface.colormod[3];
7438         }
7439         if (r_refdef.fogenabled)
7440         {
7441                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7442                 {
7443                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7444                         f2 = 1 - f1;
7445                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7446                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7447                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7448                 }
7449         }
7450 //      R_Mesh_ResetTextureState();
7451         R_SetupShader_Generic_NoTexture(false, false);
7452         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7453         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7454 }
7455
7456 void R_DrawNoModel(entity_render_t *ent)
7457 {
7458         vec3_t org;
7459         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7460         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7461                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7462         else
7463                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7464 }
7465
7466 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7467 {
7468         vec3_t right1, right2, diff, normal;
7469
7470         VectorSubtract (org2, org1, normal);
7471
7472         // calculate 'right' vector for start
7473         VectorSubtract (r_refdef.view.origin, org1, diff);
7474         CrossProduct (normal, diff, right1);
7475         VectorNormalize (right1);
7476
7477         // calculate 'right' vector for end
7478         VectorSubtract (r_refdef.view.origin, org2, diff);
7479         CrossProduct (normal, diff, right2);
7480         VectorNormalize (right2);
7481
7482         vert[ 0] = org1[0] + width * right1[0];
7483         vert[ 1] = org1[1] + width * right1[1];
7484         vert[ 2] = org1[2] + width * right1[2];
7485         vert[ 3] = org1[0] - width * right1[0];
7486         vert[ 4] = org1[1] - width * right1[1];
7487         vert[ 5] = org1[2] - width * right1[2];
7488         vert[ 6] = org2[0] - width * right2[0];
7489         vert[ 7] = org2[1] - width * right2[1];
7490         vert[ 8] = org2[2] - width * right2[2];
7491         vert[ 9] = org2[0] + width * right2[0];
7492         vert[10] = org2[1] + width * right2[1];
7493         vert[11] = org2[2] + width * right2[2];
7494 }
7495
7496 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)
7497 {
7498         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7499         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7500         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7501         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7502         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7503         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7504         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7505         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7506         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7507         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7508         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7509         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7510 }
7511
7512 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7513 {
7514         int i;
7515         float *vertex3f;
7516         float v[3];
7517         VectorSet(v, x, y, z);
7518         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7519                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7520                         break;
7521         if (i == mesh->numvertices)
7522         {
7523                 if (mesh->numvertices < mesh->maxvertices)
7524                 {
7525                         VectorCopy(v, vertex3f);
7526                         mesh->numvertices++;
7527                 }
7528                 return mesh->numvertices;
7529         }
7530         else
7531                 return i;
7532 }
7533
7534 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7535 {
7536         int i;
7537         int *e, element[3];
7538         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7539         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7540         e = mesh->element3i + mesh->numtriangles * 3;
7541         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7542         {
7543                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7544                 if (mesh->numtriangles < mesh->maxtriangles)
7545                 {
7546                         *e++ = element[0];
7547                         *e++ = element[1];
7548                         *e++ = element[2];
7549                         mesh->numtriangles++;
7550                 }
7551                 element[1] = element[2];
7552         }
7553 }
7554
7555 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7556 {
7557         int i;
7558         int *e, element[3];
7559         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7560         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7561         e = mesh->element3i + mesh->numtriangles * 3;
7562         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7563         {
7564                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7565                 if (mesh->numtriangles < mesh->maxtriangles)
7566                 {
7567                         *e++ = element[0];
7568                         *e++ = element[1];
7569                         *e++ = element[2];
7570                         mesh->numtriangles++;
7571                 }
7572                 element[1] = element[2];
7573         }
7574 }
7575
7576 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7577 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7578 {
7579         int planenum, planenum2;
7580         int w;
7581         int tempnumpoints;
7582         mplane_t *plane, *plane2;
7583         double maxdist;
7584         double temppoints[2][256*3];
7585         // figure out how large a bounding box we need to properly compute this brush
7586         maxdist = 0;
7587         for (w = 0;w < numplanes;w++)
7588                 maxdist = max(maxdist, fabs(planes[w].dist));
7589         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7590         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7591         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7592         {
7593                 w = 0;
7594                 tempnumpoints = 4;
7595                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7596                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7597                 {
7598                         if (planenum2 == planenum)
7599                                 continue;
7600                         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);
7601                         w = !w;
7602                 }
7603                 if (tempnumpoints < 3)
7604                         continue;
7605                 // generate elements forming a triangle fan for this polygon
7606                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7607         }
7608 }
7609
7610 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)
7611 {
7612         texturelayer_t *layer;
7613         layer = t->currentlayers + t->currentnumlayers++;
7614         layer->type = type;
7615         layer->depthmask = depthmask;
7616         layer->blendfunc1 = blendfunc1;
7617         layer->blendfunc2 = blendfunc2;
7618         layer->texture = texture;
7619         layer->texmatrix = *matrix;
7620         layer->color[0] = r;
7621         layer->color[1] = g;
7622         layer->color[2] = b;
7623         layer->color[3] = a;
7624 }
7625
7626 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7627 {
7628         if(parms[0] == 0 && parms[1] == 0)
7629                 return false;
7630         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7631                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7632                         return false;
7633         return true;
7634 }
7635
7636 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7637 {
7638         double index, f;
7639         index = parms[2] + rsurface.shadertime * parms[3];
7640         index -= floor(index);
7641         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7642         {
7643         default:
7644         case Q3WAVEFUNC_NONE:
7645         case Q3WAVEFUNC_NOISE:
7646         case Q3WAVEFUNC_COUNT:
7647                 f = 0;
7648                 break;
7649         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7650         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7651         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7652         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7653         case Q3WAVEFUNC_TRIANGLE:
7654                 index *= 4;
7655                 f = index - floor(index);
7656                 if (index < 1)
7657                 {
7658                         // f = f;
7659                 }
7660                 else if (index < 2)
7661                         f = 1 - f;
7662                 else if (index < 3)
7663                         f = -f;
7664                 else
7665                         f = -(1 - f);
7666                 break;
7667         }
7668         f = parms[0] + parms[1] * f;
7669         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7670                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7671         return (float) f;
7672 }
7673
7674 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7675 {
7676         int w, h, idx;
7677         double f;
7678         double offsetd[2];
7679         float tcmat[12];
7680         matrix4x4_t matrix, temp;
7681         switch(tcmod->tcmod)
7682         {
7683                 case Q3TCMOD_COUNT:
7684                 case Q3TCMOD_NONE:
7685                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7686                                 matrix = r_waterscrollmatrix;
7687                         else
7688                                 matrix = identitymatrix;
7689                         break;
7690                 case Q3TCMOD_ENTITYTRANSLATE:
7691                         // this is used in Q3 to allow the gamecode to control texcoord
7692                         // scrolling on the entity, which is not supported in darkplaces yet.
7693                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7694                         break;
7695                 case Q3TCMOD_ROTATE:
7696                         f = tcmod->parms[0] * rsurface.shadertime;
7697                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7698                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7699                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7700                         break;
7701                 case Q3TCMOD_SCALE:
7702                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7703                         break;
7704                 case Q3TCMOD_SCROLL:
7705                         // extra care is needed because of precision breakdown with large values of time
7706                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7707                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7708                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7709                         break;
7710                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7711                         w = (int) tcmod->parms[0];
7712                         h = (int) tcmod->parms[1];
7713                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7714                         f = f - floor(f);
7715                         idx = (int) floor(f * w * h);
7716                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7717                         break;
7718                 case Q3TCMOD_STRETCH:
7719                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7720                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7721                         break;
7722                 case Q3TCMOD_TRANSFORM:
7723                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7724                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7725                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7726                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7727                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7728                         break;
7729                 case Q3TCMOD_TURBULENT:
7730                         // this is handled in the RSurf_PrepareVertices function
7731                         matrix = identitymatrix;
7732                         break;
7733         }
7734         temp = *texmatrix;
7735         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7736 }
7737
7738 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7739 {
7740         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7741         char name[MAX_QPATH];
7742         skinframe_t *skinframe;
7743         unsigned char pixels[296*194];
7744         strlcpy(cache->name, skinname, sizeof(cache->name));
7745         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7746         if (developer_loading.integer)
7747                 Con_Printf("loading %s\n", name);
7748         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7749         if (!skinframe || !skinframe->base)
7750         {
7751                 unsigned char *f;
7752                 fs_offset_t filesize;
7753                 skinframe = NULL;
7754                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7755                 if (f)
7756                 {
7757                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7758                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7759                         Mem_Free(f);
7760                 }
7761         }
7762         cache->skinframe = skinframe;
7763 }
7764
7765 texture_t *R_GetCurrentTexture(texture_t *t)
7766 {
7767         int i;
7768         const entity_render_t *ent = rsurface.entity;
7769         dp_model_t *model = ent->model;
7770         q3shaderinfo_layer_tcmod_t *tcmod;
7771
7772         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7773                 return t->currentframe;
7774         t->update_lastrenderframe = r_textureframe;
7775         t->update_lastrenderentity = (void *)ent;
7776
7777         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7778                 t->camera_entity = ent->entitynumber;
7779         else
7780                 t->camera_entity = 0;
7781
7782         // switch to an alternate material if this is a q1bsp animated material
7783         {
7784                 texture_t *texture = t;
7785                 int s = rsurface.ent_skinnum;
7786                 if ((unsigned int)s >= (unsigned int)model->numskins)
7787                         s = 0;
7788                 if (model->skinscenes)
7789                 {
7790                         if (model->skinscenes[s].framecount > 1)
7791                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7792                         else
7793                                 s = model->skinscenes[s].firstframe;
7794                 }
7795                 if (s > 0)
7796                         t = t + s * model->num_surfaces;
7797                 if (t->animated)
7798                 {
7799                         // use an alternate animation if the entity's frame is not 0,
7800                         // and only if the texture has an alternate animation
7801                         if (rsurface.ent_alttextures && t->anim_total[1])
7802                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7803                         else
7804                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7805                 }
7806                 texture->currentframe = t;
7807         }
7808
7809         // update currentskinframe to be a qw skin or animation frame
7810         if (rsurface.ent_qwskin >= 0)
7811         {
7812                 i = rsurface.ent_qwskin;
7813                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7814                 {
7815                         r_qwskincache_size = cl.maxclients;
7816                         if (r_qwskincache)
7817                                 Mem_Free(r_qwskincache);
7818                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7819                 }
7820                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7821                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7822                 t->currentskinframe = r_qwskincache[i].skinframe;
7823                 if (t->currentskinframe == NULL)
7824                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7825         }
7826         else if (t->numskinframes >= 2)
7827                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7828         if (t->backgroundnumskinframes >= 2)
7829                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7830
7831         t->currentmaterialflags = t->basematerialflags;
7832         t->currentalpha = rsurface.colormod[3];
7833         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7834                 t->currentalpha *= r_wateralpha.value;
7835         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7836                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7837         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7838                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7839         if (!(rsurface.ent_flags & RENDER_LIGHT))
7840                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7841         else if (FAKELIGHT_ENABLED)
7842         {
7843                 // no modellight if using fakelight for the map
7844         }
7845         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7846         {
7847                 // pick a model lighting mode
7848                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7849                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7850                 else
7851                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7852         }
7853         if (rsurface.ent_flags & RENDER_ADDITIVE)
7854                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7855         else if (t->currentalpha < 1)
7856                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7857         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7858         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7859                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7860         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7861                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7862         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7863                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7864         if (t->backgroundnumskinframes)
7865                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7866         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7867         {
7868                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7869                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7870         }
7871         else
7872                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7873         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7874         {
7875                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7876                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7877         }
7878         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7879                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7880
7881         // there is no tcmod
7882         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7883         {
7884                 t->currenttexmatrix = r_waterscrollmatrix;
7885                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7886         }
7887         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7888         {
7889                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7890                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7891         }
7892
7893         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7894                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7895         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7896                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7897
7898         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7899         if (t->currentskinframe->qpixels)
7900                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7901         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7902         if (!t->basetexture)
7903                 t->basetexture = r_texture_notexture;
7904         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7905         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7906         t->nmaptexture = t->currentskinframe->nmap;
7907         if (!t->nmaptexture)
7908                 t->nmaptexture = r_texture_blanknormalmap;
7909         t->glosstexture = r_texture_black;
7910         t->glowtexture = t->currentskinframe->glow;
7911         t->fogtexture = t->currentskinframe->fog;
7912         t->reflectmasktexture = t->currentskinframe->reflect;
7913         if (t->backgroundnumskinframes)
7914         {
7915                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7916                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7917                 t->backgroundglosstexture = r_texture_black;
7918                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7919                 if (!t->backgroundnmaptexture)
7920                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7921         }
7922         else
7923         {
7924                 t->backgroundbasetexture = r_texture_white;
7925                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7926                 t->backgroundglosstexture = r_texture_black;
7927                 t->backgroundglowtexture = NULL;
7928         }
7929         t->specularpower = r_shadow_glossexponent.value;
7930         // TODO: store reference values for these in the texture?
7931         t->specularscale = 0;
7932         if (r_shadow_gloss.integer > 0)
7933         {
7934                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7935                 {
7936                         if (r_shadow_glossintensity.value > 0)
7937                         {
7938                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7939                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7940                                 t->specularscale = r_shadow_glossintensity.value;
7941                         }
7942                 }
7943                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7944                 {
7945                         t->glosstexture = r_texture_white;
7946                         t->backgroundglosstexture = r_texture_white;
7947                         t->specularscale = r_shadow_gloss2intensity.value;
7948                         t->specularpower = r_shadow_gloss2exponent.value;
7949                 }
7950         }
7951         t->specularscale *= t->specularscalemod;
7952         t->specularpower *= t->specularpowermod;
7953         t->rtlightambient = 0;
7954
7955         // lightmaps mode looks bad with dlights using actual texturing, so turn
7956         // off the colormap and glossmap, but leave the normalmap on as it still
7957         // accurately represents the shading involved
7958         if (gl_lightmaps.integer)
7959         {
7960                 t->basetexture = r_texture_grey128;
7961                 t->pantstexture = r_texture_black;
7962                 t->shirttexture = r_texture_black;
7963                 t->nmaptexture = r_texture_blanknormalmap;
7964                 t->glosstexture = r_texture_black;
7965                 t->glowtexture = NULL;
7966                 t->fogtexture = NULL;
7967                 t->reflectmasktexture = NULL;
7968                 t->backgroundbasetexture = NULL;
7969                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7970                 t->backgroundglosstexture = r_texture_black;
7971                 t->backgroundglowtexture = NULL;
7972                 t->specularscale = 0;
7973                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7974         }
7975
7976         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7977         VectorClear(t->dlightcolor);
7978         t->currentnumlayers = 0;
7979         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7980         {
7981                 int blendfunc1, blendfunc2;
7982                 qboolean depthmask;
7983                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7984                 {
7985                         blendfunc1 = GL_SRC_ALPHA;
7986                         blendfunc2 = GL_ONE;
7987                 }
7988                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7989                 {
7990                         blendfunc1 = GL_SRC_ALPHA;
7991                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7992                 }
7993                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7994                 {
7995                         blendfunc1 = t->customblendfunc[0];
7996                         blendfunc2 = t->customblendfunc[1];
7997                 }
7998                 else
7999                 {
8000                         blendfunc1 = GL_ONE;
8001                         blendfunc2 = GL_ZERO;
8002                 }
8003                 // don't colormod evilblend textures
8004                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8005                         VectorSet(t->lightmapcolor, 1, 1, 1);
8006                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8007                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8008                 {
8009                         // fullbright is not affected by r_refdef.lightmapintensity
8010                         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]);
8011                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8012                                 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]);
8013                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8014                                 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]);
8015                 }
8016                 else
8017                 {
8018                         vec3_t ambientcolor;
8019                         float colorscale;
8020                         // set the color tint used for lights affecting this surface
8021                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8022                         colorscale = 2;
8023                         // q3bsp has no lightmap updates, so the lightstylevalue that
8024                         // would normally be baked into the lightmap must be
8025                         // applied to the color
8026                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8027                         if (model->type == mod_brushq3)
8028                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8029                         colorscale *= r_refdef.lightmapintensity;
8030                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8031                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8032                         // basic lit geometry
8033                         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]);
8034                         // add pants/shirt if needed
8035                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8036                                 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]);
8037                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8038                                 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]);
8039                         // now add ambient passes if needed
8040                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8041                         {
8042                                 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]);
8043                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8044                                         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]);
8045                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8046                                         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]);
8047                         }
8048                 }
8049                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8050                         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]);
8051                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8052                 {
8053                         // if this is opaque use alpha blend which will darken the earlier
8054                         // passes cheaply.
8055                         //
8056                         // if this is an alpha blended material, all the earlier passes
8057                         // were darkened by fog already, so we only need to add the fog
8058                         // color ontop through the fog mask texture
8059                         //
8060                         // if this is an additive blended material, all the earlier passes
8061                         // were darkened by fog already, and we should not add fog color
8062                         // (because the background was not darkened, there is no fog color
8063                         // that was lost behind it).
8064                         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]);
8065                 }
8066         }
8067
8068         return t->currentframe;
8069 }
8070
8071 rsurfacestate_t rsurface;
8072
8073 void RSurf_ActiveWorldEntity(void)
8074 {
8075         dp_model_t *model = r_refdef.scene.worldmodel;
8076         //if (rsurface.entity == r_refdef.scene.worldentity)
8077         //      return;
8078         rsurface.entity = r_refdef.scene.worldentity;
8079         rsurface.skeleton = NULL;
8080         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8081         rsurface.ent_skinnum = 0;
8082         rsurface.ent_qwskin = -1;
8083         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8084         rsurface.shadertime = r_refdef.scene.time;
8085         rsurface.matrix = identitymatrix;
8086         rsurface.inversematrix = identitymatrix;
8087         rsurface.matrixscale = 1;
8088         rsurface.inversematrixscale = 1;
8089         R_EntityMatrix(&identitymatrix);
8090         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8091         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8092         rsurface.fograngerecip = r_refdef.fograngerecip;
8093         rsurface.fogheightfade = r_refdef.fogheightfade;
8094         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8095         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8096         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8097         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8098         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8099         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8100         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8101         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8102         rsurface.colormod[3] = 1;
8103         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);
8104         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8105         rsurface.frameblend[0].lerp = 1;
8106         rsurface.ent_alttextures = false;
8107         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8108         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8109         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8110         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8111         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8112         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8113         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8114         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8115         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8116         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8117         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8118         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8119         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8120         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8121         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8122         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8123         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8124         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8125         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8126         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8127         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8128         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8129         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8130         rsurface.modelelement3i = model->surfmesh.data_element3i;
8131         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8132         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8133         rsurface.modelelement3s = model->surfmesh.data_element3s;
8134         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8135         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8136         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8137         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8138         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8139         rsurface.modelsurfaces = model->data_surfaces;
8140         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8141         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8142         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8143         rsurface.modelgeneratedvertex = false;
8144         rsurface.batchgeneratedvertex = false;
8145         rsurface.batchfirstvertex = 0;
8146         rsurface.batchnumvertices = 0;
8147         rsurface.batchfirsttriangle = 0;
8148         rsurface.batchnumtriangles = 0;
8149         rsurface.batchvertex3f  = NULL;
8150         rsurface.batchvertex3f_vertexbuffer = NULL;
8151         rsurface.batchvertex3f_bufferoffset = 0;
8152         rsurface.batchsvector3f = NULL;
8153         rsurface.batchsvector3f_vertexbuffer = NULL;
8154         rsurface.batchsvector3f_bufferoffset = 0;
8155         rsurface.batchtvector3f = NULL;
8156         rsurface.batchtvector3f_vertexbuffer = NULL;
8157         rsurface.batchtvector3f_bufferoffset = 0;
8158         rsurface.batchnormal3f  = NULL;
8159         rsurface.batchnormal3f_vertexbuffer = NULL;
8160         rsurface.batchnormal3f_bufferoffset = 0;
8161         rsurface.batchlightmapcolor4f = NULL;
8162         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8163         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8164         rsurface.batchtexcoordtexture2f = NULL;
8165         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8166         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8167         rsurface.batchtexcoordlightmap2f = NULL;
8168         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8169         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8170         rsurface.batchvertexmesh = NULL;
8171         rsurface.batchvertexmeshbuffer = NULL;
8172         rsurface.batchvertex3fbuffer = NULL;
8173         rsurface.batchelement3i = NULL;
8174         rsurface.batchelement3i_indexbuffer = NULL;
8175         rsurface.batchelement3i_bufferoffset = 0;
8176         rsurface.batchelement3s = NULL;
8177         rsurface.batchelement3s_indexbuffer = NULL;
8178         rsurface.batchelement3s_bufferoffset = 0;
8179         rsurface.passcolor4f = NULL;
8180         rsurface.passcolor4f_vertexbuffer = NULL;
8181         rsurface.passcolor4f_bufferoffset = 0;
8182 }
8183
8184 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8185 {
8186         dp_model_t *model = ent->model;
8187         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8188         //      return;
8189         rsurface.entity = (entity_render_t *)ent;
8190         rsurface.skeleton = ent->skeleton;
8191         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8192         rsurface.ent_skinnum = ent->skinnum;
8193         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;
8194         rsurface.ent_flags = ent->flags;
8195         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8196         rsurface.matrix = ent->matrix;
8197         rsurface.inversematrix = ent->inversematrix;
8198         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8199         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8200         R_EntityMatrix(&rsurface.matrix);
8201         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8202         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8203         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8204         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8205         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8206         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8207         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8208         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8209         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8210         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8211         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8212         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8213         rsurface.colormod[3] = ent->alpha;
8214         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8215         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8216         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8217         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8218         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8219         if (ent->model->brush.submodel && !prepass)
8220         {
8221                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8222                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8223         }
8224         if (model->surfmesh.isanimated && model->AnimateVertices)
8225         {
8226                 if (ent->animcache_vertex3f)
8227                 {
8228                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8229                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8230                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8231                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8232                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8233                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8234                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8235                 }
8236                 else if (wanttangents)
8237                 {
8238                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8239                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8240                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8241                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8242                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8243                         rsurface.modelvertexmesh = NULL;
8244                         rsurface.modelvertexmeshbuffer = NULL;
8245                         rsurface.modelvertex3fbuffer = NULL;
8246                 }
8247                 else if (wantnormals)
8248                 {
8249                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8250                         rsurface.modelsvector3f = NULL;
8251                         rsurface.modeltvector3f = NULL;
8252                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8253                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8254                         rsurface.modelvertexmesh = NULL;
8255                         rsurface.modelvertexmeshbuffer = NULL;
8256                         rsurface.modelvertex3fbuffer = NULL;
8257                 }
8258                 else
8259                 {
8260                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8261                         rsurface.modelsvector3f = NULL;
8262                         rsurface.modeltvector3f = NULL;
8263                         rsurface.modelnormal3f = NULL;
8264                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8265                         rsurface.modelvertexmesh = NULL;
8266                         rsurface.modelvertexmeshbuffer = NULL;
8267                         rsurface.modelvertex3fbuffer = NULL;
8268                 }
8269                 rsurface.modelvertex3f_vertexbuffer = 0;
8270                 rsurface.modelvertex3f_bufferoffset = 0;
8271                 rsurface.modelsvector3f_vertexbuffer = 0;
8272                 rsurface.modelsvector3f_bufferoffset = 0;
8273                 rsurface.modeltvector3f_vertexbuffer = 0;
8274                 rsurface.modeltvector3f_bufferoffset = 0;
8275                 rsurface.modelnormal3f_vertexbuffer = 0;
8276                 rsurface.modelnormal3f_bufferoffset = 0;
8277                 rsurface.modelgeneratedvertex = true;
8278         }
8279         else
8280         {
8281                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8282                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8283                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8284                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8285                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8286                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8287                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8288                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8289                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8290                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8291                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8292                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8293                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8294                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8295                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8296                 rsurface.modelgeneratedvertex = false;
8297         }
8298         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8299         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8300         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8301         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8302         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8303         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8304         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8305         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8306         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8307         rsurface.modelelement3i = model->surfmesh.data_element3i;
8308         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8309         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8310         rsurface.modelelement3s = model->surfmesh.data_element3s;
8311         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8312         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8313         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8314         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8315         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8316         rsurface.modelsurfaces = model->data_surfaces;
8317         rsurface.batchgeneratedvertex = false;
8318         rsurface.batchfirstvertex = 0;
8319         rsurface.batchnumvertices = 0;
8320         rsurface.batchfirsttriangle = 0;
8321         rsurface.batchnumtriangles = 0;
8322         rsurface.batchvertex3f  = NULL;
8323         rsurface.batchvertex3f_vertexbuffer = NULL;
8324         rsurface.batchvertex3f_bufferoffset = 0;
8325         rsurface.batchsvector3f = NULL;
8326         rsurface.batchsvector3f_vertexbuffer = NULL;
8327         rsurface.batchsvector3f_bufferoffset = 0;
8328         rsurface.batchtvector3f = NULL;
8329         rsurface.batchtvector3f_vertexbuffer = NULL;
8330         rsurface.batchtvector3f_bufferoffset = 0;
8331         rsurface.batchnormal3f  = NULL;
8332         rsurface.batchnormal3f_vertexbuffer = NULL;
8333         rsurface.batchnormal3f_bufferoffset = 0;
8334         rsurface.batchlightmapcolor4f = NULL;
8335         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8336         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8337         rsurface.batchtexcoordtexture2f = NULL;
8338         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8339         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8340         rsurface.batchtexcoordlightmap2f = NULL;
8341         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8342         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8343         rsurface.batchvertexmesh = NULL;
8344         rsurface.batchvertexmeshbuffer = NULL;
8345         rsurface.batchvertex3fbuffer = NULL;
8346         rsurface.batchelement3i = NULL;
8347         rsurface.batchelement3i_indexbuffer = NULL;
8348         rsurface.batchelement3i_bufferoffset = 0;
8349         rsurface.batchelement3s = NULL;
8350         rsurface.batchelement3s_indexbuffer = NULL;
8351         rsurface.batchelement3s_bufferoffset = 0;
8352         rsurface.passcolor4f = NULL;
8353         rsurface.passcolor4f_vertexbuffer = NULL;
8354         rsurface.passcolor4f_bufferoffset = 0;
8355 }
8356
8357 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)
8358 {
8359         rsurface.entity = r_refdef.scene.worldentity;
8360         rsurface.skeleton = NULL;
8361         rsurface.ent_skinnum = 0;
8362         rsurface.ent_qwskin = -1;
8363         rsurface.ent_flags = entflags;
8364         rsurface.shadertime = r_refdef.scene.time - shadertime;
8365         rsurface.modelnumvertices = numvertices;
8366         rsurface.modelnumtriangles = numtriangles;
8367         rsurface.matrix = *matrix;
8368         rsurface.inversematrix = *inversematrix;
8369         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8370         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8371         R_EntityMatrix(&rsurface.matrix);
8372         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8373         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8374         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8375         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8376         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8377         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8378         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8379         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8380         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8381         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8382         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8383         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8384         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);
8385         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8386         rsurface.frameblend[0].lerp = 1;
8387         rsurface.ent_alttextures = false;
8388         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8389         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8390         if (wanttangents)
8391         {
8392                 rsurface.modelvertex3f = (float *)vertex3f;
8393                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8394                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8395                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8396         }
8397         else if (wantnormals)
8398         {
8399                 rsurface.modelvertex3f = (float *)vertex3f;
8400                 rsurface.modelsvector3f = NULL;
8401                 rsurface.modeltvector3f = NULL;
8402                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8403         }
8404         else
8405         {
8406                 rsurface.modelvertex3f = (float *)vertex3f;
8407                 rsurface.modelsvector3f = NULL;
8408                 rsurface.modeltvector3f = NULL;
8409                 rsurface.modelnormal3f = NULL;
8410         }
8411         rsurface.modelvertexmesh = NULL;
8412         rsurface.modelvertexmeshbuffer = NULL;
8413         rsurface.modelvertex3fbuffer = NULL;
8414         rsurface.modelvertex3f_vertexbuffer = 0;
8415         rsurface.modelvertex3f_bufferoffset = 0;
8416         rsurface.modelsvector3f_vertexbuffer = 0;
8417         rsurface.modelsvector3f_bufferoffset = 0;
8418         rsurface.modeltvector3f_vertexbuffer = 0;
8419         rsurface.modeltvector3f_bufferoffset = 0;
8420         rsurface.modelnormal3f_vertexbuffer = 0;
8421         rsurface.modelnormal3f_bufferoffset = 0;
8422         rsurface.modelgeneratedvertex = true;
8423         rsurface.modellightmapcolor4f  = (float *)color4f;
8424         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8425         rsurface.modellightmapcolor4f_bufferoffset = 0;
8426         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8427         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8428         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8429         rsurface.modeltexcoordlightmap2f  = NULL;
8430         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8431         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8432         rsurface.modelelement3i = (int *)element3i;
8433         rsurface.modelelement3i_indexbuffer = NULL;
8434         rsurface.modelelement3i_bufferoffset = 0;
8435         rsurface.modelelement3s = (unsigned short *)element3s;
8436         rsurface.modelelement3s_indexbuffer = NULL;
8437         rsurface.modelelement3s_bufferoffset = 0;
8438         rsurface.modellightmapoffsets = NULL;
8439         rsurface.modelsurfaces = NULL;
8440         rsurface.batchgeneratedvertex = false;
8441         rsurface.batchfirstvertex = 0;
8442         rsurface.batchnumvertices = 0;
8443         rsurface.batchfirsttriangle = 0;
8444         rsurface.batchnumtriangles = 0;
8445         rsurface.batchvertex3f  = NULL;
8446         rsurface.batchvertex3f_vertexbuffer = NULL;
8447         rsurface.batchvertex3f_bufferoffset = 0;
8448         rsurface.batchsvector3f = NULL;
8449         rsurface.batchsvector3f_vertexbuffer = NULL;
8450         rsurface.batchsvector3f_bufferoffset = 0;
8451         rsurface.batchtvector3f = NULL;
8452         rsurface.batchtvector3f_vertexbuffer = NULL;
8453         rsurface.batchtvector3f_bufferoffset = 0;
8454         rsurface.batchnormal3f  = NULL;
8455         rsurface.batchnormal3f_vertexbuffer = NULL;
8456         rsurface.batchnormal3f_bufferoffset = 0;
8457         rsurface.batchlightmapcolor4f = NULL;
8458         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8459         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8460         rsurface.batchtexcoordtexture2f = NULL;
8461         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8462         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8463         rsurface.batchtexcoordlightmap2f = NULL;
8464         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8465         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8466         rsurface.batchvertexmesh = NULL;
8467         rsurface.batchvertexmeshbuffer = NULL;
8468         rsurface.batchvertex3fbuffer = NULL;
8469         rsurface.batchelement3i = NULL;
8470         rsurface.batchelement3i_indexbuffer = NULL;
8471         rsurface.batchelement3i_bufferoffset = 0;
8472         rsurface.batchelement3s = NULL;
8473         rsurface.batchelement3s_indexbuffer = NULL;
8474         rsurface.batchelement3s_bufferoffset = 0;
8475         rsurface.passcolor4f = NULL;
8476         rsurface.passcolor4f_vertexbuffer = NULL;
8477         rsurface.passcolor4f_bufferoffset = 0;
8478
8479         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8480         {
8481                 if ((wantnormals || wanttangents) && !normal3f)
8482                 {
8483                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8484                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8485                 }
8486                 if (wanttangents && !svector3f)
8487                 {
8488                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8489                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8490                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8491                 }
8492         }
8493 }
8494
8495 float RSurf_FogPoint(const float *v)
8496 {
8497         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8498         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8499         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8500         float FogHeightFade = r_refdef.fogheightfade;
8501         float fogfrac;
8502         unsigned int fogmasktableindex;
8503         if (r_refdef.fogplaneviewabove)
8504                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8505         else
8506                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8507         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8508         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8509 }
8510
8511 float RSurf_FogVertex(const float *v)
8512 {
8513         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8514         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8515         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8516         float FogHeightFade = rsurface.fogheightfade;
8517         float fogfrac;
8518         unsigned int fogmasktableindex;
8519         if (r_refdef.fogplaneviewabove)
8520                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8521         else
8522                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8523         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8524         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8525 }
8526
8527 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8528 {
8529         int i;
8530         for (i = 0;i < numelements;i++)
8531                 outelement3i[i] = inelement3i[i] + adjust;
8532 }
8533
8534 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8535 extern cvar_t gl_vbo;
8536 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8537 {
8538         int deformindex;
8539         int firsttriangle;
8540         int numtriangles;
8541         int firstvertex;
8542         int endvertex;
8543         int numvertices;
8544         int surfacefirsttriangle;
8545         int surfacenumtriangles;
8546         int surfacefirstvertex;
8547         int surfaceendvertex;
8548         int surfacenumvertices;
8549         int batchnumvertices;
8550         int batchnumtriangles;
8551         int needsupdate;
8552         int i, j;
8553         qboolean gaps;
8554         qboolean dynamicvertex;
8555         float amplitude;
8556         float animpos;
8557         float scale;
8558         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8559         float waveparms[4];
8560         q3shaderinfo_deform_t *deform;
8561         const msurface_t *surface, *firstsurface;
8562         r_vertexmesh_t *vertexmesh;
8563         if (!texturenumsurfaces)
8564                 return;
8565         // find vertex range of this surface batch
8566         gaps = false;
8567         firstsurface = texturesurfacelist[0];
8568         firsttriangle = firstsurface->num_firsttriangle;
8569         batchnumvertices = 0;
8570         batchnumtriangles = 0;
8571         firstvertex = endvertex = firstsurface->num_firstvertex;
8572         for (i = 0;i < texturenumsurfaces;i++)
8573         {
8574                 surface = texturesurfacelist[i];
8575                 if (surface != firstsurface + i)
8576                         gaps = true;
8577                 surfacefirstvertex = surface->num_firstvertex;
8578                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8579                 surfacenumvertices = surface->num_vertices;
8580                 surfacenumtriangles = surface->num_triangles;
8581                 if (firstvertex > surfacefirstvertex)
8582                         firstvertex = surfacefirstvertex;
8583                 if (endvertex < surfaceendvertex)
8584                         endvertex = surfaceendvertex;
8585                 batchnumvertices += surfacenumvertices;
8586                 batchnumtriangles += surfacenumtriangles;
8587         }
8588
8589         // we now know the vertex range used, and if there are any gaps in it
8590         rsurface.batchfirstvertex = firstvertex;
8591         rsurface.batchnumvertices = endvertex - firstvertex;
8592         rsurface.batchfirsttriangle = firsttriangle;
8593         rsurface.batchnumtriangles = batchnumtriangles;
8594
8595         // this variable holds flags for which properties have been updated that
8596         // may require regenerating vertexmesh array...
8597         needsupdate = 0;
8598
8599         // check if any dynamic vertex processing must occur
8600         dynamicvertex = false;
8601
8602         // if there is a chance of animated vertex colors, it's a dynamic batch
8603         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8604         {
8605                 dynamicvertex = true;
8606                 batchneed |= BATCHNEED_NOGAPS;
8607                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8608         }
8609
8610         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8611         {
8612                 switch (deform->deform)
8613                 {
8614                 default:
8615                 case Q3DEFORM_PROJECTIONSHADOW:
8616                 case Q3DEFORM_TEXT0:
8617                 case Q3DEFORM_TEXT1:
8618                 case Q3DEFORM_TEXT2:
8619                 case Q3DEFORM_TEXT3:
8620                 case Q3DEFORM_TEXT4:
8621                 case Q3DEFORM_TEXT5:
8622                 case Q3DEFORM_TEXT6:
8623                 case Q3DEFORM_TEXT7:
8624                 case Q3DEFORM_NONE:
8625                         break;
8626                 case Q3DEFORM_AUTOSPRITE:
8627                         dynamicvertex = true;
8628                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8629                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8630                         break;
8631                 case Q3DEFORM_AUTOSPRITE2:
8632                         dynamicvertex = true;
8633                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8634                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8635                         break;
8636                 case Q3DEFORM_NORMAL:
8637                         dynamicvertex = true;
8638                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8639                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8640                         break;
8641                 case Q3DEFORM_WAVE:
8642                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8643                                 break; // if wavefunc is a nop, ignore this transform
8644                         dynamicvertex = true;
8645                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8646                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8647                         break;
8648                 case Q3DEFORM_BULGE:
8649                         dynamicvertex = true;
8650                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8651                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8652                         break;
8653                 case Q3DEFORM_MOVE:
8654                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8655                                 break; // if wavefunc is a nop, ignore this transform
8656                         dynamicvertex = true;
8657                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8658                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8659                         break;
8660                 }
8661         }
8662         switch(rsurface.texture->tcgen.tcgen)
8663         {
8664         default:
8665         case Q3TCGEN_TEXTURE:
8666                 break;
8667         case Q3TCGEN_LIGHTMAP:
8668                 dynamicvertex = true;
8669                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8670                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8671                 break;
8672         case Q3TCGEN_VECTOR:
8673                 dynamicvertex = true;
8674                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8675                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8676                 break;
8677         case Q3TCGEN_ENVIRONMENT:
8678                 dynamicvertex = true;
8679                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8680                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8681                 break;
8682         }
8683         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8684         {
8685                 dynamicvertex = true;
8686                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8687                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8688         }
8689
8690         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8691         {
8692                 dynamicvertex = true;
8693                 batchneed |= BATCHNEED_NOGAPS;
8694                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8695         }
8696
8697         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8698         {
8699                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8700                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8701                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8702                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8703                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8704                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8705                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8706         }
8707
8708         // when the model data has no vertex buffer (dynamic mesh), we need to
8709         // eliminate gaps
8710         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8711                 batchneed |= BATCHNEED_NOGAPS;
8712
8713         // if needsupdate, we have to do a dynamic vertex batch for sure
8714         if (needsupdate & batchneed)
8715                 dynamicvertex = true;
8716
8717         // see if we need to build vertexmesh from arrays
8718         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8719                 dynamicvertex = true;
8720
8721         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8722         // also some drivers strongly dislike firstvertex
8723         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8724                 dynamicvertex = true;
8725
8726         rsurface.batchvertex3f = rsurface.modelvertex3f;
8727         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8728         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8729         rsurface.batchsvector3f = rsurface.modelsvector3f;
8730         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8731         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8732         rsurface.batchtvector3f = rsurface.modeltvector3f;
8733         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8734         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8735         rsurface.batchnormal3f = rsurface.modelnormal3f;
8736         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8737         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8738         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8739         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8740         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8741         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8742         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8743         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8744         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8745         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8746         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8747         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8748         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8749         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8750         rsurface.batchelement3i = rsurface.modelelement3i;
8751         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8752         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8753         rsurface.batchelement3s = rsurface.modelelement3s;
8754         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8755         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8756
8757         // if any dynamic vertex processing has to occur in software, we copy the
8758         // entire surface list together before processing to rebase the vertices
8759         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8760         //
8761         // if any gaps exist and we do not have a static vertex buffer, we have to
8762         // copy the surface list together to avoid wasting upload bandwidth on the
8763         // vertices in the gaps.
8764         //
8765         // if gaps exist and we have a static vertex buffer, we still have to
8766         // combine the index buffer ranges into one dynamic index buffer.
8767         //
8768         // in all cases we end up with data that can be drawn in one call.
8769
8770         if (!dynamicvertex)
8771         {
8772                 // static vertex data, just set pointers...
8773                 rsurface.batchgeneratedvertex = false;
8774                 // if there are gaps, we want to build a combined index buffer,
8775                 // otherwise use the original static buffer with an appropriate offset
8776                 if (gaps)
8777                 {
8778                         // build a new triangle elements array for this batch
8779                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8780                         rsurface.batchfirsttriangle = 0;
8781                         numtriangles = 0;
8782                         for (i = 0;i < texturenumsurfaces;i++)
8783                         {
8784                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8785                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8786                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8787                                 numtriangles += surfacenumtriangles;
8788                         }
8789                         rsurface.batchelement3i_indexbuffer = NULL;
8790                         rsurface.batchelement3i_bufferoffset = 0;
8791                         rsurface.batchelement3s = NULL;
8792                         rsurface.batchelement3s_indexbuffer = NULL;
8793                         rsurface.batchelement3s_bufferoffset = 0;
8794                         if (endvertex <= 65536)
8795                         {
8796                                 // make a 16bit (unsigned short) index array if possible
8797                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8798                                 for (i = 0;i < numtriangles*3;i++)
8799                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8800                         }
8801                 }
8802                 return;
8803         }
8804
8805         // something needs software processing, do it for real...
8806         // we only directly handle separate array data in this case and then
8807         // generate interleaved data if needed...
8808         rsurface.batchgeneratedvertex = true;
8809
8810         // now copy the vertex data into a combined array and make an index array
8811         // (this is what Quake3 does all the time)
8812         //if (gaps || rsurface.batchfirstvertex)
8813         {
8814                 rsurface.batchvertex3fbuffer = NULL;
8815                 rsurface.batchvertexmesh = NULL;
8816                 rsurface.batchvertexmeshbuffer = NULL;
8817                 rsurface.batchvertex3f = NULL;
8818                 rsurface.batchvertex3f_vertexbuffer = NULL;
8819                 rsurface.batchvertex3f_bufferoffset = 0;
8820                 rsurface.batchsvector3f = NULL;
8821                 rsurface.batchsvector3f_vertexbuffer = NULL;
8822                 rsurface.batchsvector3f_bufferoffset = 0;
8823                 rsurface.batchtvector3f = NULL;
8824                 rsurface.batchtvector3f_vertexbuffer = NULL;
8825                 rsurface.batchtvector3f_bufferoffset = 0;
8826                 rsurface.batchnormal3f = NULL;
8827                 rsurface.batchnormal3f_vertexbuffer = NULL;
8828                 rsurface.batchnormal3f_bufferoffset = 0;
8829                 rsurface.batchlightmapcolor4f = NULL;
8830                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8831                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8832                 rsurface.batchtexcoordtexture2f = NULL;
8833                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8834                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8835                 rsurface.batchtexcoordlightmap2f = NULL;
8836                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8837                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8838                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8839                 rsurface.batchelement3i_indexbuffer = NULL;
8840                 rsurface.batchelement3i_bufferoffset = 0;
8841                 rsurface.batchelement3s = NULL;
8842                 rsurface.batchelement3s_indexbuffer = NULL;
8843                 rsurface.batchelement3s_bufferoffset = 0;
8844                 // we'll only be setting up certain arrays as needed
8845                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8846                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8847                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8848                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8849                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8850                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8851                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8852                 {
8853                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8854                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8855                 }
8856                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8857                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8858                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8859                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8860                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8861                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8862                 numvertices = 0;
8863                 numtriangles = 0;
8864                 for (i = 0;i < texturenumsurfaces;i++)
8865                 {
8866                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8867                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8868                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8869                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8870                         // copy only the data requested
8871                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8872                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8873                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8874                         {
8875                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8876                                 {
8877                                         if (rsurface.batchvertex3f)
8878                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8879                                         else
8880                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8881                                 }
8882                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8883                                 {
8884                                         if (rsurface.modelnormal3f)
8885                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8886                                         else
8887                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8888                                 }
8889                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8890                                 {
8891                                         if (rsurface.modelsvector3f)
8892                                         {
8893                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8894                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8895                                         }
8896                                         else
8897                                         {
8898                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8899                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8900                                         }
8901                                 }
8902                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8903                                 {
8904                                         if (rsurface.modellightmapcolor4f)
8905                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8906                                         else
8907                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8908                                 }
8909                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8910                                 {
8911                                         if (rsurface.modeltexcoordtexture2f)
8912                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8913                                         else
8914                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8915                                 }
8916                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8917                                 {
8918                                         if (rsurface.modeltexcoordlightmap2f)
8919                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8920                                         else
8921                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8922                                 }
8923                         }
8924                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8925                         numvertices += surfacenumvertices;
8926                         numtriangles += surfacenumtriangles;
8927                 }
8928
8929                 // generate a 16bit index array as well if possible
8930                 // (in general, dynamic batches fit)
8931                 if (numvertices <= 65536)
8932                 {
8933                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8934                         for (i = 0;i < numtriangles*3;i++)
8935                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8936                 }
8937
8938                 // since we've copied everything, the batch now starts at 0
8939                 rsurface.batchfirstvertex = 0;
8940                 rsurface.batchnumvertices = batchnumvertices;
8941                 rsurface.batchfirsttriangle = 0;
8942                 rsurface.batchnumtriangles = batchnumtriangles;
8943         }
8944
8945         // q1bsp surfaces rendered in vertex color mode have to have colors
8946         // calculated based on lightstyles
8947         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8948         {
8949                 // generate color arrays for the surfaces in this list
8950                 int c[4];
8951                 int scale;
8952                 int size3;
8953                 const int *offsets;
8954                 const unsigned char *lm;
8955                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8956                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8957                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8958                 numvertices = 0;
8959                 for (i = 0;i < texturenumsurfaces;i++)
8960                 {
8961                         surface = texturesurfacelist[i];
8962                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8963                         surfacenumvertices = surface->num_vertices;
8964                         if (surface->lightmapinfo->samples)
8965                         {
8966                                 for (j = 0;j < surfacenumvertices;j++)
8967                                 {
8968                                         lm = surface->lightmapinfo->samples + offsets[j];
8969                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8970                                         VectorScale(lm, scale, c);
8971                                         if (surface->lightmapinfo->styles[1] != 255)
8972                                         {
8973                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8974                                                 lm += size3;
8975                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8976                                                 VectorMA(c, scale, lm, c);
8977                                                 if (surface->lightmapinfo->styles[2] != 255)
8978                                                 {
8979                                                         lm += size3;
8980                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8981                                                         VectorMA(c, scale, lm, c);
8982                                                         if (surface->lightmapinfo->styles[3] != 255)
8983                                                         {
8984                                                                 lm += size3;
8985                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8986                                                                 VectorMA(c, scale, lm, c);
8987                                                         }
8988                                                 }
8989                                         }
8990                                         c[0] >>= 7;
8991                                         c[1] >>= 7;
8992                                         c[2] >>= 7;
8993                                         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);
8994                                         numvertices++;
8995                                 }
8996                         }
8997                         else
8998                         {
8999                                 for (j = 0;j < surfacenumvertices;j++)
9000                                 {
9001                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9002                                         numvertices++;
9003                                 }
9004                         }
9005                 }
9006         }
9007
9008         // if vertices are deformed (sprite flares and things in maps, possibly
9009         // water waves, bulges and other deformations), modify the copied vertices
9010         // in place
9011         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9012         {
9013                 switch (deform->deform)
9014                 {
9015                 default:
9016                 case Q3DEFORM_PROJECTIONSHADOW:
9017                 case Q3DEFORM_TEXT0:
9018                 case Q3DEFORM_TEXT1:
9019                 case Q3DEFORM_TEXT2:
9020                 case Q3DEFORM_TEXT3:
9021                 case Q3DEFORM_TEXT4:
9022                 case Q3DEFORM_TEXT5:
9023                 case Q3DEFORM_TEXT6:
9024                 case Q3DEFORM_TEXT7:
9025                 case Q3DEFORM_NONE:
9026                         break;
9027                 case Q3DEFORM_AUTOSPRITE:
9028                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9029                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9030                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9031                         VectorNormalize(newforward);
9032                         VectorNormalize(newright);
9033                         VectorNormalize(newup);
9034 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9035 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9036 //                      rsurface.batchvertex3f_bufferoffset = 0;
9037 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9038 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9039 //                      rsurface.batchsvector3f_bufferoffset = 0;
9040 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9041 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9042 //                      rsurface.batchtvector3f_bufferoffset = 0;
9043 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9044 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9045 //                      rsurface.batchnormal3f_bufferoffset = 0;
9046                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9047                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9048                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9049                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9050                                 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);
9051                         // a single autosprite surface can contain multiple sprites...
9052                         for (j = 0;j < batchnumvertices - 3;j += 4)
9053                         {
9054                                 VectorClear(center);
9055                                 for (i = 0;i < 4;i++)
9056                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9057                                 VectorScale(center, 0.25f, center);
9058                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9059                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9060                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9061                                 for (i = 0;i < 4;i++)
9062                                 {
9063                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9064                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9065                                 }
9066                         }
9067                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9068                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9069                         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);
9070                         break;
9071                 case Q3DEFORM_AUTOSPRITE2:
9072                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9073                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9074                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9075                         VectorNormalize(newforward);
9076                         VectorNormalize(newright);
9077                         VectorNormalize(newup);
9078 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9079 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9080 //                      rsurface.batchvertex3f_bufferoffset = 0;
9081                         {
9082                                 const float *v1, *v2;
9083                                 vec3_t start, end;
9084                                 float f, l;
9085                                 struct
9086                                 {
9087                                         float length2;
9088                                         const float *v1;
9089                                         const float *v2;
9090                                 }
9091                                 shortest[2];
9092                                 memset(shortest, 0, sizeof(shortest));
9093                                 // a single autosprite surface can contain multiple sprites...
9094                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9095                                 {
9096                                         VectorClear(center);
9097                                         for (i = 0;i < 4;i++)
9098                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9099                                         VectorScale(center, 0.25f, center);
9100                                         // find the two shortest edges, then use them to define the
9101                                         // axis vectors for rotating around the central axis
9102                                         for (i = 0;i < 6;i++)
9103                                         {
9104                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9105                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9106                                                 l = VectorDistance2(v1, v2);
9107                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9108                                                 if (v1[2] != v2[2])
9109                                                         l += (1.0f / 1024.0f);
9110                                                 if (shortest[0].length2 > l || i == 0)
9111                                                 {
9112                                                         shortest[1] = shortest[0];
9113                                                         shortest[0].length2 = l;
9114                                                         shortest[0].v1 = v1;
9115                                                         shortest[0].v2 = v2;
9116                                                 }
9117                                                 else if (shortest[1].length2 > l || i == 1)
9118                                                 {
9119                                                         shortest[1].length2 = l;
9120                                                         shortest[1].v1 = v1;
9121                                                         shortest[1].v2 = v2;
9122                                                 }
9123                                         }
9124                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9125                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9126                                         // this calculates the right vector from the shortest edge
9127                                         // and the up vector from the edge midpoints
9128                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9129                                         VectorNormalize(right);
9130                                         VectorSubtract(end, start, up);
9131                                         VectorNormalize(up);
9132                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9133                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9134                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9135                                         VectorNegate(forward, forward);
9136                                         VectorReflect(forward, 0, up, forward);
9137                                         VectorNormalize(forward);
9138                                         CrossProduct(up, forward, newright);
9139                                         VectorNormalize(newright);
9140                                         // rotate the quad around the up axis vector, this is made
9141                                         // especially easy by the fact we know the quad is flat,
9142                                         // so we only have to subtract the center position and
9143                                         // measure distance along the right vector, and then
9144                                         // multiply that by the newright vector and add back the
9145                                         // center position
9146                                         // we also need to subtract the old position to undo the
9147                                         // displacement from the center, which we do with a
9148                                         // DotProduct, the subtraction/addition of center is also
9149                                         // optimized into DotProducts here
9150                                         l = DotProduct(right, center);
9151                                         for (i = 0;i < 4;i++)
9152                                         {
9153                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9154                                                 f = DotProduct(right, v1) - l;
9155                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9156                                         }
9157                                 }
9158                         }
9159                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9160                         {
9161 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9162 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9163 //                              rsurface.batchnormal3f_bufferoffset = 0;
9164                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9165                         }
9166                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9167                         {
9168 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9169 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9170 //                              rsurface.batchsvector3f_bufferoffset = 0;
9171 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9172 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9173 //                              rsurface.batchtvector3f_bufferoffset = 0;
9174                                 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);
9175                         }
9176                         break;
9177                 case Q3DEFORM_NORMAL:
9178                         // deform the normals to make reflections wavey
9179                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9180                         rsurface.batchnormal3f_vertexbuffer = NULL;
9181                         rsurface.batchnormal3f_bufferoffset = 0;
9182                         for (j = 0;j < batchnumvertices;j++)
9183                         {
9184                                 float vertex[3];
9185                                 float *normal = rsurface.batchnormal3f + 3*j;
9186                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9187                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9188                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9189                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9190                                 VectorNormalize(normal);
9191                         }
9192                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9193                         {
9194 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9195 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9196 //                              rsurface.batchsvector3f_bufferoffset = 0;
9197 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9198 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9199 //                              rsurface.batchtvector3f_bufferoffset = 0;
9200                                 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);
9201                         }
9202                         break;
9203                 case Q3DEFORM_WAVE:
9204                         // deform vertex array to make wavey water and flags and such
9205                         waveparms[0] = deform->waveparms[0];
9206                         waveparms[1] = deform->waveparms[1];
9207                         waveparms[2] = deform->waveparms[2];
9208                         waveparms[3] = deform->waveparms[3];
9209                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9210                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9211                         // this is how a divisor of vertex influence on deformation
9212                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9213                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9214 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9215 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9216 //                      rsurface.batchvertex3f_bufferoffset = 0;
9217 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9218 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9219 //                      rsurface.batchnormal3f_bufferoffset = 0;
9220                         for (j = 0;j < batchnumvertices;j++)
9221                         {
9222                                 // if the wavefunc depends on time, evaluate it per-vertex
9223                                 if (waveparms[3])
9224                                 {
9225                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9226                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9227                                 }
9228                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9229                         }
9230                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9231                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9232                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9233                         {
9234 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9235 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9236 //                              rsurface.batchsvector3f_bufferoffset = 0;
9237 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9238 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9239 //                              rsurface.batchtvector3f_bufferoffset = 0;
9240                                 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);
9241                         }
9242                         break;
9243                 case Q3DEFORM_BULGE:
9244                         // deform vertex array to make the surface have moving bulges
9245 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9246 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9247 //                      rsurface.batchvertex3f_bufferoffset = 0;
9248 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9249 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9250 //                      rsurface.batchnormal3f_bufferoffset = 0;
9251                         for (j = 0;j < batchnumvertices;j++)
9252                         {
9253                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9254                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9255                         }
9256                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9257                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9258                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9259                         {
9260 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9261 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9262 //                              rsurface.batchsvector3f_bufferoffset = 0;
9263 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9264 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9265 //                              rsurface.batchtvector3f_bufferoffset = 0;
9266                                 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);
9267                         }
9268                         break;
9269                 case Q3DEFORM_MOVE:
9270                         // deform vertex array
9271                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9272                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9273                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9274                         VectorScale(deform->parms, scale, waveparms);
9275 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9276 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9277 //                      rsurface.batchvertex3f_bufferoffset = 0;
9278                         for (j = 0;j < batchnumvertices;j++)
9279                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9280                         break;
9281                 }
9282         }
9283
9284         // generate texcoords based on the chosen texcoord source
9285         switch(rsurface.texture->tcgen.tcgen)
9286         {
9287         default:
9288         case Q3TCGEN_TEXTURE:
9289                 break;
9290         case Q3TCGEN_LIGHTMAP:
9291 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9292 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9293 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9294                 if (rsurface.batchtexcoordlightmap2f)
9295                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9296                 break;
9297         case Q3TCGEN_VECTOR:
9298 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9299 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9300 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9301                 for (j = 0;j < batchnumvertices;j++)
9302                 {
9303                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9304                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9305                 }
9306                 break;
9307         case Q3TCGEN_ENVIRONMENT:
9308                 // make environment reflections using a spheremap
9309                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9310                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9311                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9312                 for (j = 0;j < batchnumvertices;j++)
9313                 {
9314                         // identical to Q3A's method, but executed in worldspace so
9315                         // carried models can be shiny too
9316
9317                         float viewer[3], d, reflected[3], worldreflected[3];
9318
9319                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9320                         // VectorNormalize(viewer);
9321
9322                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9323
9324                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9325                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9326                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9327                         // note: this is proportinal to viewer, so we can normalize later
9328
9329                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9330                         VectorNormalize(worldreflected);
9331
9332                         // note: this sphere map only uses world x and z!
9333                         // so positive and negative y will LOOK THE SAME.
9334                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9335                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9336                 }
9337                 break;
9338         }
9339         // the only tcmod that needs software vertex processing is turbulent, so
9340         // check for it here and apply the changes if needed
9341         // and we only support that as the first one
9342         // (handling a mixture of turbulent and other tcmods would be problematic
9343         //  without punting it entirely to a software path)
9344         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9345         {
9346                 amplitude = rsurface.texture->tcmods[0].parms[1];
9347                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9348 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9349 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9350 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9351                 for (j = 0;j < batchnumvertices;j++)
9352                 {
9353                         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);
9354                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9355                 }
9356         }
9357
9358         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9359         {
9360                 // convert the modified arrays to vertex structs
9361 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9362 //              rsurface.batchvertexmeshbuffer = NULL;
9363                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9364                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9365                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9366                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9367                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9368                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9369                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9370                 {
9371                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9372                         {
9373                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9374                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9375                         }
9376                 }
9377                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9378                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9379                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9380                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9381                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9382                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9383                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9384                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9385                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9386         }
9387 }
9388
9389 void RSurf_DrawBatch(void)
9390 {
9391         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9392         // through the pipeline, killing it earlier in the pipeline would have
9393         // per-surface overhead rather than per-batch overhead, so it's best to
9394         // reject it here, before it hits glDraw.
9395         if (rsurface.batchnumtriangles == 0)
9396                 return;
9397 #if 0
9398         // batch debugging code
9399         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9400         {
9401                 int i;
9402                 int j;
9403                 int c;
9404                 const int *e;
9405                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9406                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9407                 {
9408                         c = e[i];
9409                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9410                         {
9411                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9412                                 {
9413                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9414                                                 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);
9415                                         break;
9416                                 }
9417                         }
9418                 }
9419         }
9420 #endif
9421         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);
9422 }
9423
9424 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9425 {
9426         // pick the closest matching water plane
9427         int planeindex, vertexindex, bestplaneindex = -1;
9428         float d, bestd;
9429         vec3_t vert;
9430         const float *v;
9431         r_waterstate_waterplane_t *p;
9432         qboolean prepared = false;
9433         bestd = 0;
9434         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9435         {
9436                 if(p->camera_entity != rsurface.texture->camera_entity)
9437                         continue;
9438                 d = 0;
9439                 if(!prepared)
9440                 {
9441                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9442                         prepared = true;
9443                         if(rsurface.batchnumvertices == 0)
9444                                 break;
9445                 }
9446                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9447                 {
9448                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9449                         d += fabs(PlaneDiff(vert, &p->plane));
9450                 }
9451                 if (bestd > d || bestplaneindex < 0)
9452                 {
9453                         bestd = d;
9454                         bestplaneindex = planeindex;
9455                 }
9456         }
9457         return bestplaneindex;
9458         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9459         // this situation though, as it might be better to render single larger
9460         // batches with useless stuff (backface culled for example) than to
9461         // render multiple smaller batches
9462 }
9463
9464 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9465 {
9466         int i;
9467         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9468         rsurface.passcolor4f_vertexbuffer = 0;
9469         rsurface.passcolor4f_bufferoffset = 0;
9470         for (i = 0;i < rsurface.batchnumvertices;i++)
9471                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9472 }
9473
9474 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9475 {
9476         int i;
9477         float f;
9478         const float *v;
9479         const float *c;
9480         float *c2;
9481         if (rsurface.passcolor4f)
9482         {
9483                 // generate color arrays
9484                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9485                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9486                 rsurface.passcolor4f_vertexbuffer = 0;
9487                 rsurface.passcolor4f_bufferoffset = 0;
9488                 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)
9489                 {
9490                         f = RSurf_FogVertex(v);
9491                         c2[0] = c[0] * f;
9492                         c2[1] = c[1] * f;
9493                         c2[2] = c[2] * f;
9494                         c2[3] = c[3];
9495                 }
9496         }
9497         else
9498         {
9499                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9500                 rsurface.passcolor4f_vertexbuffer = 0;
9501                 rsurface.passcolor4f_bufferoffset = 0;
9502                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9503                 {
9504                         f = RSurf_FogVertex(v);
9505                         c2[0] = f;
9506                         c2[1] = f;
9507                         c2[2] = f;
9508                         c2[3] = 1;
9509                 }
9510         }
9511 }
9512
9513 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9514 {
9515         int i;
9516         float f;
9517         const float *v;
9518         const float *c;
9519         float *c2;
9520         if (!rsurface.passcolor4f)
9521                 return;
9522         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9523         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9524         rsurface.passcolor4f_vertexbuffer = 0;
9525         rsurface.passcolor4f_bufferoffset = 0;
9526         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)
9527         {
9528                 f = RSurf_FogVertex(v);
9529                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9530                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9531                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9532                 c2[3] = c[3];
9533         }
9534 }
9535
9536 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9537 {
9538         int i;
9539         const float *c;
9540         float *c2;
9541         if (!rsurface.passcolor4f)
9542                 return;
9543         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9544         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9545         rsurface.passcolor4f_vertexbuffer = 0;
9546         rsurface.passcolor4f_bufferoffset = 0;
9547         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9548         {
9549                 c2[0] = c[0] * r;
9550                 c2[1] = c[1] * g;
9551                 c2[2] = c[2] * b;
9552                 c2[3] = c[3] * a;
9553         }
9554 }
9555
9556 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9557 {
9558         int i;
9559         const float *c;
9560         float *c2;
9561         if (!rsurface.passcolor4f)
9562                 return;
9563         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9564         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9565         rsurface.passcolor4f_vertexbuffer = 0;
9566         rsurface.passcolor4f_bufferoffset = 0;
9567         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9568         {
9569                 c2[0] = c[0] + r_refdef.scene.ambient;
9570                 c2[1] = c[1] + r_refdef.scene.ambient;
9571                 c2[2] = c[2] + r_refdef.scene.ambient;
9572                 c2[3] = c[3];
9573         }
9574 }
9575
9576 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9577 {
9578         // TODO: optimize
9579         rsurface.passcolor4f = NULL;
9580         rsurface.passcolor4f_vertexbuffer = 0;
9581         rsurface.passcolor4f_bufferoffset = 0;
9582         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9583         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9584         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9585         GL_Color(r, g, b, a);
9586         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9587         RSurf_DrawBatch();
9588 }
9589
9590 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9591 {
9592         // TODO: optimize applyfog && applycolor case
9593         // just apply fog if necessary, and tint the fog color array if necessary
9594         rsurface.passcolor4f = NULL;
9595         rsurface.passcolor4f_vertexbuffer = 0;
9596         rsurface.passcolor4f_bufferoffset = 0;
9597         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9598         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9599         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9600         GL_Color(r, g, b, a);
9601         RSurf_DrawBatch();
9602 }
9603
9604 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9605 {
9606         // TODO: optimize
9607         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9608         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9609         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9610         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9611         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9612         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9613         GL_Color(r, g, b, a);
9614         RSurf_DrawBatch();
9615 }
9616
9617 static void RSurf_DrawBatch_GL11_ClampColor(void)
9618 {
9619         int i;
9620         const float *c1;
9621         float *c2;
9622         if (!rsurface.passcolor4f)
9623                 return;
9624         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9625         {
9626                 c2[0] = bound(0.0f, c1[0], 1.0f);
9627                 c2[1] = bound(0.0f, c1[1], 1.0f);
9628                 c2[2] = bound(0.0f, c1[2], 1.0f);
9629                 c2[3] = bound(0.0f, c1[3], 1.0f);
9630         }
9631 }
9632
9633 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9634 {
9635         int i;
9636         float f;
9637         const float *v;
9638         const float *n;
9639         float *c;
9640         //vec3_t eyedir;
9641
9642         // fake shading
9643         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9644         rsurface.passcolor4f_vertexbuffer = 0;
9645         rsurface.passcolor4f_bufferoffset = 0;
9646         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)
9647         {
9648                 f = -DotProduct(r_refdef.view.forward, n);
9649                 f = max(0, f);
9650                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9651                 f *= r_refdef.lightmapintensity;
9652                 Vector4Set(c, f, f, f, 1);
9653         }
9654 }
9655
9656 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9657 {
9658         RSurf_DrawBatch_GL11_ApplyFakeLight();
9659         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9660         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9661         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9662         GL_Color(r, g, b, a);
9663         RSurf_DrawBatch();
9664 }
9665
9666 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9667 {
9668         int i;
9669         float f;
9670         float alpha;
9671         const float *v;
9672         const float *n;
9673         float *c;
9674         vec3_t ambientcolor;
9675         vec3_t diffusecolor;
9676         vec3_t lightdir;
9677         // TODO: optimize
9678         // model lighting
9679         VectorCopy(rsurface.modellight_lightdir, lightdir);
9680         f = 0.5f * r_refdef.lightmapintensity;
9681         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9682         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9683         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9684         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9685         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9686         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9687         alpha = *a;
9688         if (VectorLength2(diffusecolor) > 0)
9689         {
9690                 // q3-style directional shading
9691                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9692                 rsurface.passcolor4f_vertexbuffer = 0;
9693                 rsurface.passcolor4f_bufferoffset = 0;
9694                 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)
9695                 {
9696                         if ((f = DotProduct(n, lightdir)) > 0)
9697                                 VectorMA(ambientcolor, f, diffusecolor, c);
9698                         else
9699                                 VectorCopy(ambientcolor, c);
9700                         c[3] = alpha;
9701                 }
9702                 *r = 1;
9703                 *g = 1;
9704                 *b = 1;
9705                 *a = 1;
9706                 *applycolor = false;
9707         }
9708         else
9709         {
9710                 *r = ambientcolor[0];
9711                 *g = ambientcolor[1];
9712                 *b = ambientcolor[2];
9713                 rsurface.passcolor4f = NULL;
9714                 rsurface.passcolor4f_vertexbuffer = 0;
9715                 rsurface.passcolor4f_bufferoffset = 0;
9716         }
9717 }
9718
9719 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9720 {
9721         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9722         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9723         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9724         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9725         GL_Color(r, g, b, a);
9726         RSurf_DrawBatch();
9727 }
9728
9729 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9730 {
9731         int i;
9732         float f;
9733         const float *v;
9734         float *c;
9735
9736         // fake shading
9737         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9738         rsurface.passcolor4f_vertexbuffer = 0;
9739         rsurface.passcolor4f_bufferoffset = 0;
9740
9741         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9742         {
9743                 f = 1 - RSurf_FogVertex(v);
9744                 c[0] = r;
9745                 c[1] = g;
9746                 c[2] = b;
9747                 c[3] = f * a;
9748         }
9749 }
9750
9751 void RSurf_SetupDepthAndCulling(void)
9752 {
9753         // submodels are biased to avoid z-fighting with world surfaces that they
9754         // may be exactly overlapping (avoids z-fighting artifacts on certain
9755         // doors and things in Quake maps)
9756         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9757         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9758         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9759         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9760 }
9761
9762 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9763 {
9764         // transparent sky would be ridiculous
9765         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9766                 return;
9767         R_SetupShader_Generic_NoTexture(false, false);
9768         skyrenderlater = true;
9769         RSurf_SetupDepthAndCulling();
9770         GL_DepthMask(true);
9771         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9772         // skymasking on them, and Quake3 never did sky masking (unlike
9773         // software Quake and software Quake2), so disable the sky masking
9774         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9775         // and skymasking also looks very bad when noclipping outside the
9776         // level, so don't use it then either.
9777         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9778         {
9779                 R_Mesh_ResetTextureState();
9780                 if (skyrendermasked)
9781                 {
9782                         R_SetupShader_DepthOrShadow(false);
9783                         // depth-only (masking)
9784                         GL_ColorMask(0,0,0,0);
9785                         // just to make sure that braindead drivers don't draw
9786                         // anything despite that colormask...
9787                         GL_BlendFunc(GL_ZERO, GL_ONE);
9788                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9789                         if (rsurface.batchvertex3fbuffer)
9790                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9791                         else
9792                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9793                 }
9794                 else
9795                 {
9796                         R_SetupShader_Generic_NoTexture(false, false);
9797                         // fog sky
9798                         GL_BlendFunc(GL_ONE, GL_ZERO);
9799                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9800                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9801                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9802                 }
9803                 RSurf_DrawBatch();
9804                 if (skyrendermasked)
9805                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9806         }
9807         R_Mesh_ResetTextureState();
9808         GL_Color(1, 1, 1, 1);
9809 }
9810
9811 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9812 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9813 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9814 {
9815         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9816                 return;
9817         if (prepass)
9818         {
9819                 // render screenspace normalmap to texture
9820                 GL_DepthMask(true);
9821                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9822                 RSurf_DrawBatch();
9823                 return;
9824         }
9825
9826         // bind lightmap texture
9827
9828         // water/refraction/reflection/camera surfaces have to be handled specially
9829         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9830         {
9831                 int start, end, startplaneindex;
9832                 for (start = 0;start < texturenumsurfaces;start = end)
9833                 {
9834                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9835                         if(startplaneindex < 0)
9836                         {
9837                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9838                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9839                                 end = start + 1;
9840                                 continue;
9841                         }
9842                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9843                                 ;
9844                         // now that we have a batch using the same planeindex, render it
9845                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9846                         {
9847                                 // render water or distortion background
9848                                 GL_DepthMask(true);
9849                                 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);
9850                                 RSurf_DrawBatch();
9851                                 // blend surface on top
9852                                 GL_DepthMask(false);
9853                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9854                                 RSurf_DrawBatch();
9855                         }
9856                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9857                         {
9858                                 // render surface with reflection texture as input
9859                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9860                                 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);
9861                                 RSurf_DrawBatch();
9862                         }
9863                 }
9864                 return;
9865         }
9866
9867         // render surface batch normally
9868         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9869         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);
9870         RSurf_DrawBatch();
9871 }
9872
9873 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9874 {
9875         // OpenGL 1.3 path - anything not completely ancient
9876         qboolean applycolor;
9877         qboolean applyfog;
9878         int layerindex;
9879         const texturelayer_t *layer;
9880         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);
9881         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9882
9883         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9884         {
9885                 vec4_t layercolor;
9886                 int layertexrgbscale;
9887                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9888                 {
9889                         if (layerindex == 0)
9890                                 GL_AlphaTest(true);
9891                         else
9892                         {
9893                                 GL_AlphaTest(false);
9894                                 GL_DepthFunc(GL_EQUAL);
9895                         }
9896                 }
9897                 GL_DepthMask(layer->depthmask && writedepth);
9898                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9899                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9900                 {
9901                         layertexrgbscale = 4;
9902                         VectorScale(layer->color, 0.25f, layercolor);
9903                 }
9904                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9905                 {
9906                         layertexrgbscale = 2;
9907                         VectorScale(layer->color, 0.5f, layercolor);
9908                 }
9909                 else
9910                 {
9911                         layertexrgbscale = 1;
9912                         VectorScale(layer->color, 1.0f, layercolor);
9913                 }
9914                 layercolor[3] = layer->color[3];
9915                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9916                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9917                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9918                 switch (layer->type)
9919                 {
9920                 case TEXTURELAYERTYPE_LITTEXTURE:
9921                         // single-pass lightmapped texture with 2x rgbscale
9922                         R_Mesh_TexBind(0, r_texture_white);
9923                         R_Mesh_TexMatrix(0, NULL);
9924                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9925                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9926                         R_Mesh_TexBind(1, layer->texture);
9927                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9928                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9929                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9930                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9931                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9932                         else if (FAKELIGHT_ENABLED)
9933                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9934                         else if (rsurface.uselightmaptexture)
9935                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9936                         else
9937                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9938                         break;
9939                 case TEXTURELAYERTYPE_TEXTURE:
9940                         // singletexture unlit texture with transparency support
9941                         R_Mesh_TexBind(0, layer->texture);
9942                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9943                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9944                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9945                         R_Mesh_TexBind(1, 0);
9946                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9947                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9948                         break;
9949                 case TEXTURELAYERTYPE_FOG:
9950                         // singletexture fogging
9951                         if (layer->texture)
9952                         {
9953                                 R_Mesh_TexBind(0, layer->texture);
9954                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9955                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9956                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9957                         }
9958                         else
9959                         {
9960                                 R_Mesh_TexBind(0, 0);
9961                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9962                         }
9963                         R_Mesh_TexBind(1, 0);
9964                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9965                         // generate a color array for the fog pass
9966                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9967                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9968                         RSurf_DrawBatch();
9969                         break;
9970                 default:
9971                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9972                 }
9973         }
9974         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9975         {
9976                 GL_DepthFunc(GL_LEQUAL);
9977                 GL_AlphaTest(false);
9978         }
9979 }
9980
9981 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9982 {
9983         // OpenGL 1.1 - crusty old voodoo path
9984         qboolean applyfog;
9985         int layerindex;
9986         const texturelayer_t *layer;
9987         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);
9988         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9989
9990         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9991         {
9992                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9993                 {
9994                         if (layerindex == 0)
9995                                 GL_AlphaTest(true);
9996                         else
9997                         {
9998                                 GL_AlphaTest(false);
9999                                 GL_DepthFunc(GL_EQUAL);
10000                         }
10001                 }
10002                 GL_DepthMask(layer->depthmask && writedepth);
10003                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10004                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10005                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10006                 switch (layer->type)
10007                 {
10008                 case TEXTURELAYERTYPE_LITTEXTURE:
10009                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10010                         {
10011                                 // two-pass lit texture with 2x rgbscale
10012                                 // first the lightmap pass
10013                                 R_Mesh_TexBind(0, r_texture_white);
10014                                 R_Mesh_TexMatrix(0, NULL);
10015                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10016                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10017                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10018                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10019                                 else if (FAKELIGHT_ENABLED)
10020                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10021                                 else if (rsurface.uselightmaptexture)
10022                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10023                                 else
10024                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10025                                 // then apply the texture to it
10026                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10027                                 R_Mesh_TexBind(0, layer->texture);
10028                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10029                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10030                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10031                                 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);
10032                         }
10033                         else
10034                         {
10035                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10036                                 R_Mesh_TexBind(0, layer->texture);
10037                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10038                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10039                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10040                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10041                                         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);
10042                                 else
10043                                         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);
10044                         }
10045                         break;
10046                 case TEXTURELAYERTYPE_TEXTURE:
10047                         // singletexture unlit texture with transparency support
10048                         R_Mesh_TexBind(0, layer->texture);
10049                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10050                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10051                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10052                         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);
10053                         break;
10054                 case TEXTURELAYERTYPE_FOG:
10055                         // singletexture fogging
10056                         if (layer->texture)
10057                         {
10058                                 R_Mesh_TexBind(0, layer->texture);
10059                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10060                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10061                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10062                         }
10063                         else
10064                         {
10065                                 R_Mesh_TexBind(0, 0);
10066                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10067                         }
10068                         // generate a color array for the fog pass
10069                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10070                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10071                         RSurf_DrawBatch();
10072                         break;
10073                 default:
10074                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10075                 }
10076         }
10077         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10078         {
10079                 GL_DepthFunc(GL_LEQUAL);
10080                 GL_AlphaTest(false);
10081         }
10082 }
10083
10084 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10085 {
10086         int vi;
10087         int j;
10088         r_vertexgeneric_t *batchvertex;
10089         float c[4];
10090
10091 //      R_Mesh_ResetTextureState();
10092         R_SetupShader_Generic_NoTexture(false, false);
10093
10094         if(rsurface.texture && rsurface.texture->currentskinframe)
10095         {
10096                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10097                 c[3] *= rsurface.texture->currentalpha;
10098         }
10099         else
10100         {
10101                 c[0] = 1;
10102                 c[1] = 0;
10103                 c[2] = 1;
10104                 c[3] = 1;
10105         }
10106
10107         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10108         {
10109                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10110                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10111                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10112         }
10113
10114         // brighten it up (as texture value 127 means "unlit")
10115         c[0] *= 2 * r_refdef.view.colorscale;
10116         c[1] *= 2 * r_refdef.view.colorscale;
10117         c[2] *= 2 * r_refdef.view.colorscale;
10118
10119         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10120                 c[3] *= r_wateralpha.value;
10121
10122         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10123         {
10124                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10125                 GL_DepthMask(false);
10126         }
10127         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10128         {
10129                 GL_BlendFunc(GL_ONE, GL_ONE);
10130                 GL_DepthMask(false);
10131         }
10132         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10133         {
10134                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10135                 GL_DepthMask(false);
10136         }
10137         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10138         {
10139                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10140                 GL_DepthMask(false);
10141         }
10142         else
10143         {
10144                 GL_BlendFunc(GL_ONE, GL_ZERO);
10145                 GL_DepthMask(writedepth);
10146         }
10147
10148         if (r_showsurfaces.integer == 3)
10149         {
10150                 rsurface.passcolor4f = NULL;
10151
10152                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10153                 {
10154                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10155
10156                         rsurface.passcolor4f = NULL;
10157                         rsurface.passcolor4f_vertexbuffer = 0;
10158                         rsurface.passcolor4f_bufferoffset = 0;
10159                 }
10160                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10161                 {
10162                         qboolean applycolor = true;
10163                         float one = 1.0;
10164
10165                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10166
10167                         r_refdef.lightmapintensity = 1;
10168                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10169                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10170                 }
10171                 else if (FAKELIGHT_ENABLED)
10172                 {
10173                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10174
10175                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10176                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10177                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10178                 }
10179                 else
10180                 {
10181                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10182
10183                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10184                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10185                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10186                 }
10187
10188                 if(!rsurface.passcolor4f)
10189                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10190
10191                 RSurf_DrawBatch_GL11_ApplyAmbient();
10192                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10193                 if(r_refdef.fogenabled)
10194                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10195                 RSurf_DrawBatch_GL11_ClampColor();
10196
10197                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10198                 R_SetupShader_Generic_NoTexture(false, false);
10199                 RSurf_DrawBatch();
10200         }
10201         else if (!r_refdef.view.showdebug)
10202         {
10203                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10204                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10205                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10206                 {
10207                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10208                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10209                 }
10210                 R_Mesh_PrepareVertices_Generic_Unlock();
10211                 RSurf_DrawBatch();
10212         }
10213         else if (r_showsurfaces.integer == 4)
10214         {
10215                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10216                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10217                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10218                 {
10219                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10220                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10221                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10222                 }
10223                 R_Mesh_PrepareVertices_Generic_Unlock();
10224                 RSurf_DrawBatch();
10225         }
10226         else if (r_showsurfaces.integer == 2)
10227         {
10228                 const int *e;
10229                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10230                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10231                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10232                 {
10233                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10234                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10235                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10236                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10237                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10238                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10239                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10240                 }
10241                 R_Mesh_PrepareVertices_Generic_Unlock();
10242                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10243         }
10244         else
10245         {
10246                 int texturesurfaceindex;
10247                 int k;
10248                 const msurface_t *surface;
10249                 float surfacecolor4f[4];
10250                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10251                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10252                 vi = 0;
10253                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10254                 {
10255                         surface = texturesurfacelist[texturesurfaceindex];
10256                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10257                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10258                         for (j = 0;j < surface->num_vertices;j++)
10259                         {
10260                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10261                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10262                                 vi++;
10263                         }
10264                 }
10265                 R_Mesh_PrepareVertices_Generic_Unlock();
10266                 RSurf_DrawBatch();
10267         }
10268 }
10269
10270 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10271 {
10272         CHECKGLERROR
10273         RSurf_SetupDepthAndCulling();
10274         if (r_showsurfaces.integer)
10275         {
10276                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10277                 return;
10278         }
10279         switch (vid.renderpath)
10280         {
10281         case RENDERPATH_GL20:
10282         case RENDERPATH_D3D9:
10283         case RENDERPATH_D3D10:
10284         case RENDERPATH_D3D11:
10285         case RENDERPATH_SOFT:
10286         case RENDERPATH_GLES2:
10287                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10288                 break;
10289         case RENDERPATH_GL13:
10290         case RENDERPATH_GLES1:
10291                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10292                 break;
10293         case RENDERPATH_GL11:
10294                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10295                 break;
10296         }
10297         CHECKGLERROR
10298 }
10299
10300 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10301 {
10302         CHECKGLERROR
10303         RSurf_SetupDepthAndCulling();
10304         if (r_showsurfaces.integer)
10305         {
10306                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10307                 return;
10308         }
10309         switch (vid.renderpath)
10310         {
10311         case RENDERPATH_GL20:
10312         case RENDERPATH_D3D9:
10313         case RENDERPATH_D3D10:
10314         case RENDERPATH_D3D11:
10315         case RENDERPATH_SOFT:
10316         case RENDERPATH_GLES2:
10317                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10318                 break;
10319         case RENDERPATH_GL13:
10320         case RENDERPATH_GLES1:
10321                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10322                 break;
10323         case RENDERPATH_GL11:
10324                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10325                 break;
10326         }
10327         CHECKGLERROR
10328 }
10329
10330 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10331 {
10332         int i, j;
10333         int texturenumsurfaces, endsurface;
10334         texture_t *texture;
10335         const msurface_t *surface;
10336         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10337
10338         // if the model is static it doesn't matter what value we give for
10339         // wantnormals and wanttangents, so this logic uses only rules applicable
10340         // to a model, knowing that they are meaningless otherwise
10341         if (ent == r_refdef.scene.worldentity)
10342                 RSurf_ActiveWorldEntity();
10343         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10344                 RSurf_ActiveModelEntity(ent, false, false, false);
10345         else
10346         {
10347                 switch (vid.renderpath)
10348                 {
10349                 case RENDERPATH_GL20:
10350                 case RENDERPATH_D3D9:
10351                 case RENDERPATH_D3D10:
10352                 case RENDERPATH_D3D11:
10353                 case RENDERPATH_SOFT:
10354                 case RENDERPATH_GLES2:
10355                         RSurf_ActiveModelEntity(ent, true, true, false);
10356                         break;
10357                 case RENDERPATH_GL11:
10358                 case RENDERPATH_GL13:
10359                 case RENDERPATH_GLES1:
10360                         RSurf_ActiveModelEntity(ent, true, false, false);
10361                         break;
10362                 }
10363         }
10364
10365         if (r_transparentdepthmasking.integer)
10366         {
10367                 qboolean setup = false;
10368                 for (i = 0;i < numsurfaces;i = j)
10369                 {
10370                         j = i + 1;
10371                         surface = rsurface.modelsurfaces + surfacelist[i];
10372                         texture = surface->texture;
10373                         rsurface.texture = R_GetCurrentTexture(texture);
10374                         rsurface.lightmaptexture = NULL;
10375                         rsurface.deluxemaptexture = NULL;
10376                         rsurface.uselightmaptexture = false;
10377                         // scan ahead until we find a different texture
10378                         endsurface = min(i + 1024, numsurfaces);
10379                         texturenumsurfaces = 0;
10380                         texturesurfacelist[texturenumsurfaces++] = surface;
10381                         for (;j < endsurface;j++)
10382                         {
10383                                 surface = rsurface.modelsurfaces + surfacelist[j];
10384                                 if (texture != surface->texture)
10385                                         break;
10386                                 texturesurfacelist[texturenumsurfaces++] = surface;
10387                         }
10388                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10389                                 continue;
10390                         // render the range of surfaces as depth
10391                         if (!setup)
10392                         {
10393                                 setup = true;
10394                                 GL_ColorMask(0,0,0,0);
10395                                 GL_Color(1,1,1,1);
10396                                 GL_DepthTest(true);
10397                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10398                                 GL_DepthMask(true);
10399 //                              R_Mesh_ResetTextureState();
10400                                 R_SetupShader_DepthOrShadow(false);
10401                         }
10402                         RSurf_SetupDepthAndCulling();
10403                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10404                         if (rsurface.batchvertex3fbuffer)
10405                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10406                         else
10407                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10408                         RSurf_DrawBatch();
10409                 }
10410                 if (setup)
10411                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10412         }
10413
10414         for (i = 0;i < numsurfaces;i = j)
10415         {
10416                 j = i + 1;
10417                 surface = rsurface.modelsurfaces + surfacelist[i];
10418                 texture = surface->texture;
10419                 rsurface.texture = R_GetCurrentTexture(texture);
10420                 // scan ahead until we find a different texture
10421                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10422                 texturenumsurfaces = 0;
10423                 texturesurfacelist[texturenumsurfaces++] = surface;
10424                 if(FAKELIGHT_ENABLED)
10425                 {
10426                         rsurface.lightmaptexture = NULL;
10427                         rsurface.deluxemaptexture = NULL;
10428                         rsurface.uselightmaptexture = false;
10429                         for (;j < endsurface;j++)
10430                         {
10431                                 surface = rsurface.modelsurfaces + surfacelist[j];
10432                                 if (texture != surface->texture)
10433                                         break;
10434                                 texturesurfacelist[texturenumsurfaces++] = surface;
10435                         }
10436                 }
10437                 else
10438                 {
10439                         rsurface.lightmaptexture = surface->lightmaptexture;
10440                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10441                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10442                         for (;j < endsurface;j++)
10443                         {
10444                                 surface = rsurface.modelsurfaces + surfacelist[j];
10445                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10446                                         break;
10447                                 texturesurfacelist[texturenumsurfaces++] = surface;
10448                         }
10449                 }
10450                 // render the range of surfaces
10451                 if (ent == r_refdef.scene.worldentity)
10452                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10453                 else
10454                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10455         }
10456         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10457 }
10458
10459 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10460 {
10461         // transparent surfaces get pushed off into the transparent queue
10462         int surfacelistindex;
10463         const msurface_t *surface;
10464         vec3_t tempcenter, center;
10465         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10466         {
10467                 surface = texturesurfacelist[surfacelistindex];
10468                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10469                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10470                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10471                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10472                 if (queueentity->transparent_offset) // transparent offset
10473                 {
10474                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10475                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10476                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10477                 }
10478                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10479         }
10480 }
10481
10482 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10483 {
10484         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10485                 return;
10486         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10487                 return;
10488         RSurf_SetupDepthAndCulling();
10489         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10490         if (rsurface.batchvertex3fbuffer)
10491                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10492         else
10493                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10494         RSurf_DrawBatch();
10495 }
10496
10497 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10498 {
10499         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10500         CHECKGLERROR
10501         if (depthonly)
10502                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10503         else if (prepass)
10504         {
10505                 if (!rsurface.texture->currentnumlayers)
10506                         return;
10507                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10508                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10509                 else
10510                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10511         }
10512         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10513                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10514         else if (!rsurface.texture->currentnumlayers)
10515                 return;
10516         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10517         {
10518                 // in the deferred case, transparent surfaces were queued during prepass
10519                 if (!r_shadow_usingdeferredprepass)
10520                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10521         }
10522         else
10523         {
10524                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10525                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10526         }
10527         CHECKGLERROR
10528 }
10529
10530 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10531 {
10532         int i, j;
10533         texture_t *texture;
10534         R_FrameData_SetMark();
10535         // break the surface list down into batches by texture and use of lightmapping
10536         for (i = 0;i < numsurfaces;i = j)
10537         {
10538                 j = i + 1;
10539                 // texture is the base texture pointer, rsurface.texture is the
10540                 // current frame/skin the texture is directing us to use (for example
10541                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10542                 // use skin 1 instead)
10543                 texture = surfacelist[i]->texture;
10544                 rsurface.texture = R_GetCurrentTexture(texture);
10545                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10546                 {
10547                         // if this texture is not the kind we want, skip ahead to the next one
10548                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10549                                 ;
10550                         continue;
10551                 }
10552                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10553                 {
10554                         rsurface.lightmaptexture = NULL;
10555                         rsurface.deluxemaptexture = NULL;
10556                         rsurface.uselightmaptexture = false;
10557                         // simply scan ahead until we find a different texture or lightmap state
10558                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10559                                 ;
10560                 }
10561                 else
10562                 {
10563                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10564                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10565                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10566                         // simply scan ahead until we find a different texture or lightmap state
10567                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10568                                 ;
10569                 }
10570                 // render the range of surfaces
10571                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10572         }
10573         R_FrameData_ReturnToMark();
10574 }
10575
10576 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10577 {
10578         CHECKGLERROR
10579         if (depthonly)
10580                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10581         else if (prepass)
10582         {
10583                 if (!rsurface.texture->currentnumlayers)
10584                         return;
10585                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10586                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10587                 else
10588                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10589         }
10590         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10591                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10592         else if (!rsurface.texture->currentnumlayers)
10593                 return;
10594         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10595         {
10596                 // in the deferred case, transparent surfaces were queued during prepass
10597                 if (!r_shadow_usingdeferredprepass)
10598                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10599         }
10600         else
10601         {
10602                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10603                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10604         }
10605         CHECKGLERROR
10606 }
10607
10608 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10609 {
10610         int i, j;
10611         texture_t *texture;
10612         R_FrameData_SetMark();
10613         // break the surface list down into batches by texture and use of lightmapping
10614         for (i = 0;i < numsurfaces;i = j)
10615         {
10616                 j = i + 1;
10617                 // texture is the base texture pointer, rsurface.texture is the
10618                 // current frame/skin the texture is directing us to use (for example
10619                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10620                 // use skin 1 instead)
10621                 texture = surfacelist[i]->texture;
10622                 rsurface.texture = R_GetCurrentTexture(texture);
10623                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10624                 {
10625                         // if this texture is not the kind we want, skip ahead to the next one
10626                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10627                                 ;
10628                         continue;
10629                 }
10630                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10631                 {
10632                         rsurface.lightmaptexture = NULL;
10633                         rsurface.deluxemaptexture = NULL;
10634                         rsurface.uselightmaptexture = false;
10635                         // simply scan ahead until we find a different texture or lightmap state
10636                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10637                                 ;
10638                 }
10639                 else
10640                 {
10641                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10642                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10643                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10644                         // simply scan ahead until we find a different texture or lightmap state
10645                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10646                                 ;
10647                 }
10648                 // render the range of surfaces
10649                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10650         }
10651         R_FrameData_ReturnToMark();
10652 }
10653
10654 float locboxvertex3f[6*4*3] =
10655 {
10656         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10657         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10658         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10659         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10660         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10661         1,0,0, 0,0,0, 0,1,0, 1,1,0
10662 };
10663
10664 unsigned short locboxelements[6*2*3] =
10665 {
10666          0, 1, 2, 0, 2, 3,
10667          4, 5, 6, 4, 6, 7,
10668          8, 9,10, 8,10,11,
10669         12,13,14, 12,14,15,
10670         16,17,18, 16,18,19,
10671         20,21,22, 20,22,23
10672 };
10673
10674 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10675 {
10676         int i, j;
10677         cl_locnode_t *loc = (cl_locnode_t *)ent;
10678         vec3_t mins, size;
10679         float vertex3f[6*4*3];
10680         CHECKGLERROR
10681         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10682         GL_DepthMask(false);
10683         GL_DepthRange(0, 1);
10684         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10685         GL_DepthTest(true);
10686         GL_CullFace(GL_NONE);
10687         R_EntityMatrix(&identitymatrix);
10688
10689 //      R_Mesh_ResetTextureState();
10690
10691         i = surfacelist[0];
10692         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10693                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10694                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10695                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10696
10697         if (VectorCompare(loc->mins, loc->maxs))
10698         {
10699                 VectorSet(size, 2, 2, 2);
10700                 VectorMA(loc->mins, -0.5f, size, mins);
10701         }
10702         else
10703         {
10704                 VectorCopy(loc->mins, mins);
10705                 VectorSubtract(loc->maxs, loc->mins, size);
10706         }
10707
10708         for (i = 0;i < 6*4*3;)
10709                 for (j = 0;j < 3;j++, i++)
10710                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10711
10712         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10713         R_SetupShader_Generic_NoTexture(false, false);
10714         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10715 }
10716
10717 void R_DrawLocs(void)
10718 {
10719         int index;
10720         cl_locnode_t *loc, *nearestloc;
10721         vec3_t center;
10722         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10723         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10724         {
10725                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10726                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10727         }
10728 }
10729
10730 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10731 {
10732         if (decalsystem->decals)
10733                 Mem_Free(decalsystem->decals);
10734         memset(decalsystem, 0, sizeof(*decalsystem));
10735 }
10736
10737 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)
10738 {
10739         tridecal_t *decal;
10740         tridecal_t *decals;
10741         int i;
10742
10743         // expand or initialize the system
10744         if (decalsystem->maxdecals <= decalsystem->numdecals)
10745         {
10746                 decalsystem_t old = *decalsystem;
10747                 qboolean useshortelements;
10748                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10749                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10750                 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)));
10751                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10752                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10753                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10754                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10755                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10756                 if (decalsystem->numdecals)
10757                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10758                 if (old.decals)
10759                         Mem_Free(old.decals);
10760                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10761                         decalsystem->element3i[i] = i;
10762                 if (useshortelements)
10763                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10764                                 decalsystem->element3s[i] = i;
10765         }
10766
10767         // grab a decal and search for another free slot for the next one
10768         decals = decalsystem->decals;
10769         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10770         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10771                 ;
10772         decalsystem->freedecal = i;
10773         if (decalsystem->numdecals <= i)
10774                 decalsystem->numdecals = i + 1;
10775
10776         // initialize the decal
10777         decal->lived = 0;
10778         decal->triangleindex = triangleindex;
10779         decal->surfaceindex = surfaceindex;
10780         decal->decalsequence = decalsequence;
10781         decal->color4f[0][0] = c0[0];
10782         decal->color4f[0][1] = c0[1];
10783         decal->color4f[0][2] = c0[2];
10784         decal->color4f[0][3] = 1;
10785         decal->color4f[1][0] = c1[0];
10786         decal->color4f[1][1] = c1[1];
10787         decal->color4f[1][2] = c1[2];
10788         decal->color4f[1][3] = 1;
10789         decal->color4f[2][0] = c2[0];
10790         decal->color4f[2][1] = c2[1];
10791         decal->color4f[2][2] = c2[2];
10792         decal->color4f[2][3] = 1;
10793         decal->vertex3f[0][0] = v0[0];
10794         decal->vertex3f[0][1] = v0[1];
10795         decal->vertex3f[0][2] = v0[2];
10796         decal->vertex3f[1][0] = v1[0];
10797         decal->vertex3f[1][1] = v1[1];
10798         decal->vertex3f[1][2] = v1[2];
10799         decal->vertex3f[2][0] = v2[0];
10800         decal->vertex3f[2][1] = v2[1];
10801         decal->vertex3f[2][2] = v2[2];
10802         decal->texcoord2f[0][0] = t0[0];
10803         decal->texcoord2f[0][1] = t0[1];
10804         decal->texcoord2f[1][0] = t1[0];
10805         decal->texcoord2f[1][1] = t1[1];
10806         decal->texcoord2f[2][0] = t2[0];
10807         decal->texcoord2f[2][1] = t2[1];
10808         TriangleNormal(v0, v1, v2, decal->plane);
10809         VectorNormalize(decal->plane);
10810         decal->plane[3] = DotProduct(v0, decal->plane);
10811 }
10812
10813 extern cvar_t cl_decals_bias;
10814 extern cvar_t cl_decals_models;
10815 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10816 // baseparms, parms, temps
10817 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)
10818 {
10819         int cornerindex;
10820         int index;
10821         float v[9][3];
10822         const float *vertex3f;
10823         const float *normal3f;
10824         int numpoints;
10825         float points[2][9][3];
10826         float temp[3];
10827         float tc[9][2];
10828         float f;
10829         float c[9][4];
10830         const int *e;
10831
10832         e = rsurface.modelelement3i + 3*triangleindex;
10833
10834         vertex3f = rsurface.modelvertex3f;
10835         normal3f = rsurface.modelnormal3f;
10836
10837         if (normal3f)
10838         {
10839                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10840                 {
10841                         index = 3*e[cornerindex];
10842                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10843                 }
10844         }
10845         else
10846         {
10847                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10848                 {
10849                         index = 3*e[cornerindex];
10850                         VectorCopy(vertex3f + index, v[cornerindex]);
10851                 }
10852         }
10853
10854         // cull backfaces
10855         //TriangleNormal(v[0], v[1], v[2], normal);
10856         //if (DotProduct(normal, localnormal) < 0.0f)
10857         //      continue;
10858         // clip by each of the box planes formed from the projection matrix
10859         // if anything survives, we emit the decal
10860         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]);
10861         if (numpoints < 3)
10862                 return;
10863         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]);
10864         if (numpoints < 3)
10865                 return;
10866         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]);
10867         if (numpoints < 3)
10868                 return;
10869         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]);
10870         if (numpoints < 3)
10871                 return;
10872         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]);
10873         if (numpoints < 3)
10874                 return;
10875         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]);
10876         if (numpoints < 3)
10877                 return;
10878         // some part of the triangle survived, so we have to accept it...
10879         if (dynamic)
10880         {
10881                 // dynamic always uses the original triangle
10882                 numpoints = 3;
10883                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10884                 {
10885                         index = 3*e[cornerindex];
10886                         VectorCopy(vertex3f + index, v[cornerindex]);
10887                 }
10888         }
10889         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10890         {
10891                 // convert vertex positions to texcoords
10892                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10893                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10894                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10895                 // calculate distance fade from the projection origin
10896                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10897                 f = bound(0.0f, f, 1.0f);
10898                 c[cornerindex][0] = r * f;
10899                 c[cornerindex][1] = g * f;
10900                 c[cornerindex][2] = b * f;
10901                 c[cornerindex][3] = 1.0f;
10902                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10903         }
10904         if (dynamic)
10905                 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);
10906         else
10907                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10908                         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);
10909 }
10910 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)
10911 {
10912         matrix4x4_t projection;
10913         decalsystem_t *decalsystem;
10914         qboolean dynamic;
10915         dp_model_t *model;
10916         const msurface_t *surface;
10917         const msurface_t *surfaces;
10918         const int *surfacelist;
10919         const texture_t *texture;
10920         int numtriangles;
10921         int numsurfacelist;
10922         int surfacelistindex;
10923         int surfaceindex;
10924         int triangleindex;
10925         float localorigin[3];
10926         float localnormal[3];
10927         float localmins[3];
10928         float localmaxs[3];
10929         float localsize;
10930         //float normal[3];
10931         float planes[6][4];
10932         float angles[3];
10933         bih_t *bih;
10934         int bih_triangles_count;
10935         int bih_triangles[256];
10936         int bih_surfaces[256];
10937
10938         decalsystem = &ent->decalsystem;
10939         model = ent->model;
10940         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10941         {
10942                 R_DecalSystem_Reset(&ent->decalsystem);
10943                 return;
10944         }
10945
10946         if (!model->brush.data_leafs && !cl_decals_models.integer)
10947         {
10948                 if (decalsystem->model)
10949                         R_DecalSystem_Reset(decalsystem);
10950                 return;
10951         }
10952
10953         if (decalsystem->model != model)
10954                 R_DecalSystem_Reset(decalsystem);
10955         decalsystem->model = model;
10956
10957         RSurf_ActiveModelEntity(ent, true, false, false);
10958
10959         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10960         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10961         VectorNormalize(localnormal);
10962         localsize = worldsize*rsurface.inversematrixscale;
10963         localmins[0] = localorigin[0] - localsize;
10964         localmins[1] = localorigin[1] - localsize;
10965         localmins[2] = localorigin[2] - localsize;
10966         localmaxs[0] = localorigin[0] + localsize;
10967         localmaxs[1] = localorigin[1] + localsize;
10968         localmaxs[2] = localorigin[2] + localsize;
10969
10970         //VectorCopy(localnormal, planes[4]);
10971         //VectorVectors(planes[4], planes[2], planes[0]);
10972         AnglesFromVectors(angles, localnormal, NULL, false);
10973         AngleVectors(angles, planes[0], planes[2], planes[4]);
10974         VectorNegate(planes[0], planes[1]);
10975         VectorNegate(planes[2], planes[3]);
10976         VectorNegate(planes[4], planes[5]);
10977         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10978         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10979         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10980         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10981         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10982         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10983
10984 #if 1
10985 // works
10986 {
10987         matrix4x4_t forwardprojection;
10988         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10989         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10990 }
10991 #else
10992 // broken
10993 {
10994         float projectionvector[4][3];
10995         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10996         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10997         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10998         projectionvector[0][0] = planes[0][0] * ilocalsize;
10999         projectionvector[0][1] = planes[1][0] * ilocalsize;
11000         projectionvector[0][2] = planes[2][0] * ilocalsize;
11001         projectionvector[1][0] = planes[0][1] * ilocalsize;
11002         projectionvector[1][1] = planes[1][1] * ilocalsize;
11003         projectionvector[1][2] = planes[2][1] * ilocalsize;
11004         projectionvector[2][0] = planes[0][2] * ilocalsize;
11005         projectionvector[2][1] = planes[1][2] * ilocalsize;
11006         projectionvector[2][2] = planes[2][2] * ilocalsize;
11007         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11008         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11009         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11010         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11011 }
11012 #endif
11013
11014         dynamic = model->surfmesh.isanimated;
11015         numsurfacelist = model->nummodelsurfaces;
11016         surfacelist = model->sortedmodelsurfaces;
11017         surfaces = model->data_surfaces;
11018
11019         bih = NULL;
11020         bih_triangles_count = -1;
11021         if(!dynamic)
11022         {
11023                 if(model->render_bih.numleafs)
11024                         bih = &model->render_bih;
11025                 else if(model->collision_bih.numleafs)
11026                         bih = &model->collision_bih;
11027         }
11028         if(bih)
11029                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11030         if(bih_triangles_count == 0)
11031                 return;
11032         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11033                 return;
11034         if(bih_triangles_count > 0)
11035         {
11036                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11037                 {
11038                         surfaceindex = bih_surfaces[triangleindex];
11039                         surface = surfaces + surfaceindex;
11040                         texture = surface->texture;
11041                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11042                                 continue;
11043                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11044                                 continue;
11045                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11046                 }
11047         }
11048         else
11049         {
11050                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11051                 {
11052                         surfaceindex = surfacelist[surfacelistindex];
11053                         surface = surfaces + surfaceindex;
11054                         // check cull box first because it rejects more than any other check
11055                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11056                                 continue;
11057                         // skip transparent surfaces
11058                         texture = surface->texture;
11059                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11060                                 continue;
11061                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11062                                 continue;
11063                         numtriangles = surface->num_triangles;
11064                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11065                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11066                 }
11067         }
11068 }
11069
11070 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11071 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)
11072 {
11073         int renderentityindex;
11074         float worldmins[3];
11075         float worldmaxs[3];
11076         entity_render_t *ent;
11077
11078         if (!cl_decals_newsystem.integer)
11079                 return;
11080
11081         worldmins[0] = worldorigin[0] - worldsize;
11082         worldmins[1] = worldorigin[1] - worldsize;
11083         worldmins[2] = worldorigin[2] - worldsize;
11084         worldmaxs[0] = worldorigin[0] + worldsize;
11085         worldmaxs[1] = worldorigin[1] + worldsize;
11086         worldmaxs[2] = worldorigin[2] + worldsize;
11087
11088         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11089
11090         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11091         {
11092                 ent = r_refdef.scene.entities[renderentityindex];
11093                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11094                         continue;
11095
11096                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11097         }
11098 }
11099
11100 typedef struct r_decalsystem_splatqueue_s
11101 {
11102         vec3_t worldorigin;
11103         vec3_t worldnormal;
11104         float color[4];
11105         float tcrange[4];
11106         float worldsize;
11107         int decalsequence;
11108 }
11109 r_decalsystem_splatqueue_t;
11110
11111 int r_decalsystem_numqueued = 0;
11112 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11113
11114 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)
11115 {
11116         r_decalsystem_splatqueue_t *queue;
11117
11118         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11119                 return;
11120
11121         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11122         VectorCopy(worldorigin, queue->worldorigin);
11123         VectorCopy(worldnormal, queue->worldnormal);
11124         Vector4Set(queue->color, r, g, b, a);
11125         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11126         queue->worldsize = worldsize;
11127         queue->decalsequence = cl.decalsequence++;
11128 }
11129
11130 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11131 {
11132         int i;
11133         r_decalsystem_splatqueue_t *queue;
11134
11135         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11136                 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);
11137         r_decalsystem_numqueued = 0;
11138 }
11139
11140 extern cvar_t cl_decals_max;
11141 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11142 {
11143         int i;
11144         decalsystem_t *decalsystem = &ent->decalsystem;
11145         int numdecals;
11146         int killsequence;
11147         tridecal_t *decal;
11148         float frametime;
11149         float lifetime;
11150
11151         if (!decalsystem->numdecals)
11152                 return;
11153
11154         if (r_showsurfaces.integer)
11155                 return;
11156
11157         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11158         {
11159                 R_DecalSystem_Reset(decalsystem);
11160                 return;
11161         }
11162
11163         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11164         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11165
11166         if (decalsystem->lastupdatetime)
11167                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11168         else
11169                 frametime = 0;
11170         decalsystem->lastupdatetime = r_refdef.scene.time;
11171         decal = decalsystem->decals;
11172         numdecals = decalsystem->numdecals;
11173
11174         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11175         {
11176                 if (decal->color4f[0][3])
11177                 {
11178                         decal->lived += frametime;
11179                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11180                         {
11181                                 memset(decal, 0, sizeof(*decal));
11182                                 if (decalsystem->freedecal > i)
11183                                         decalsystem->freedecal = i;
11184                         }
11185                 }
11186         }
11187         decal = decalsystem->decals;
11188         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11189                 numdecals--;
11190
11191         // collapse the array by shuffling the tail decals into the gaps
11192         for (;;)
11193         {
11194                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11195                         decalsystem->freedecal++;
11196                 if (decalsystem->freedecal == numdecals)
11197                         break;
11198                 decal[decalsystem->freedecal] = decal[--numdecals];
11199         }
11200
11201         decalsystem->numdecals = numdecals;
11202
11203         if (numdecals <= 0)
11204         {
11205                 // if there are no decals left, reset decalsystem
11206                 R_DecalSystem_Reset(decalsystem);
11207         }
11208 }
11209
11210 extern skinframe_t *decalskinframe;
11211 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11212 {
11213         int i;
11214         decalsystem_t *decalsystem = &ent->decalsystem;
11215         int numdecals;
11216         tridecal_t *decal;
11217         float faderate;
11218         float alpha;
11219         float *v3f;
11220         float *c4f;
11221         float *t2f;
11222         const int *e;
11223         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11224         int numtris = 0;
11225
11226         numdecals = decalsystem->numdecals;
11227         if (!numdecals)
11228                 return;
11229
11230         if (r_showsurfaces.integer)
11231                 return;
11232
11233         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11234         {
11235                 R_DecalSystem_Reset(decalsystem);
11236                 return;
11237         }
11238
11239         // if the model is static it doesn't matter what value we give for
11240         // wantnormals and wanttangents, so this logic uses only rules applicable
11241         // to a model, knowing that they are meaningless otherwise
11242         if (ent == r_refdef.scene.worldentity)
11243                 RSurf_ActiveWorldEntity();
11244         else
11245                 RSurf_ActiveModelEntity(ent, false, false, false);
11246
11247         decalsystem->lastupdatetime = r_refdef.scene.time;
11248         decal = decalsystem->decals;
11249
11250         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11251
11252         // update vertex positions for animated models
11253         v3f = decalsystem->vertex3f;
11254         c4f = decalsystem->color4f;
11255         t2f = decalsystem->texcoord2f;
11256         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11257         {
11258                 if (!decal->color4f[0][3])
11259                         continue;
11260
11261                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11262                         continue;
11263
11264                 // skip backfaces
11265                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11266                         continue;
11267
11268                 // update color values for fading decals
11269                 if (decal->lived >= cl_decals_time.value)
11270                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11271                 else
11272                         alpha = 1.0f;
11273
11274                 c4f[ 0] = decal->color4f[0][0] * alpha;
11275                 c4f[ 1] = decal->color4f[0][1] * alpha;
11276                 c4f[ 2] = decal->color4f[0][2] * alpha;
11277                 c4f[ 3] = 1;
11278                 c4f[ 4] = decal->color4f[1][0] * alpha;
11279                 c4f[ 5] = decal->color4f[1][1] * alpha;
11280                 c4f[ 6] = decal->color4f[1][2] * alpha;
11281                 c4f[ 7] = 1;
11282                 c4f[ 8] = decal->color4f[2][0] * alpha;
11283                 c4f[ 9] = decal->color4f[2][1] * alpha;
11284                 c4f[10] = decal->color4f[2][2] * alpha;
11285                 c4f[11] = 1;
11286
11287                 t2f[0] = decal->texcoord2f[0][0];
11288                 t2f[1] = decal->texcoord2f[0][1];
11289                 t2f[2] = decal->texcoord2f[1][0];
11290                 t2f[3] = decal->texcoord2f[1][1];
11291                 t2f[4] = decal->texcoord2f[2][0];
11292                 t2f[5] = decal->texcoord2f[2][1];
11293
11294                 // update vertex positions for animated models
11295                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11296                 {
11297                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11298                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11299                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11300                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11301                 }
11302                 else
11303                 {
11304                         VectorCopy(decal->vertex3f[0], v3f);
11305                         VectorCopy(decal->vertex3f[1], v3f + 3);
11306                         VectorCopy(decal->vertex3f[2], v3f + 6);
11307                 }
11308
11309                 if (r_refdef.fogenabled)
11310                 {
11311                         alpha = RSurf_FogVertex(v3f);
11312                         VectorScale(c4f, alpha, c4f);
11313                         alpha = RSurf_FogVertex(v3f + 3);
11314                         VectorScale(c4f + 4, alpha, c4f + 4);
11315                         alpha = RSurf_FogVertex(v3f + 6);
11316                         VectorScale(c4f + 8, alpha, c4f + 8);
11317                 }
11318
11319                 v3f += 9;
11320                 c4f += 12;
11321                 t2f += 6;
11322                 numtris++;
11323         }
11324
11325         if (numtris > 0)
11326         {
11327                 r_refdef.stats.drawndecals += numtris;
11328
11329                 // now render the decals all at once
11330                 // (this assumes they all use one particle font texture!)
11331                 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);
11332 //              R_Mesh_ResetTextureState();
11333                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11334                 GL_DepthMask(false);
11335                 GL_DepthRange(0, 1);
11336                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11337                 GL_DepthTest(true);
11338                 GL_CullFace(GL_NONE);
11339                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11340                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11341                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11342         }
11343 }
11344
11345 static void R_DrawModelDecals(void)
11346 {
11347         int i, numdecals;
11348
11349         // fade faster when there are too many decals
11350         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11351         for (i = 0;i < r_refdef.scene.numentities;i++)
11352                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11353
11354         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11355         for (i = 0;i < r_refdef.scene.numentities;i++)
11356                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11357                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11358
11359         R_DecalSystem_ApplySplatEntitiesQueue();
11360
11361         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11362         for (i = 0;i < r_refdef.scene.numentities;i++)
11363                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11364
11365         r_refdef.stats.totaldecals += numdecals;
11366
11367         if (r_showsurfaces.integer)
11368                 return;
11369
11370         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11371
11372         for (i = 0;i < r_refdef.scene.numentities;i++)
11373         {
11374                 if (!r_refdef.viewcache.entityvisible[i])
11375                         continue;
11376                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11377                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11378         }
11379 }
11380
11381 extern cvar_t mod_collision_bih;
11382 void R_DrawDebugModel(void)
11383 {
11384         entity_render_t *ent = rsurface.entity;
11385         int i, j, k, l, flagsmask;
11386         const msurface_t *surface;
11387         dp_model_t *model = ent->model;
11388         vec3_t v;
11389
11390         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11391                 return;
11392
11393         if (r_showoverdraw.value > 0)
11394         {
11395                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11396                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11397                 R_SetupShader_Generic_NoTexture(false, false);
11398                 GL_DepthTest(false);
11399                 GL_DepthMask(false);
11400                 GL_DepthRange(0, 1);
11401                 GL_BlendFunc(GL_ONE, GL_ONE);
11402                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11403                 {
11404                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11405                                 continue;
11406                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11407                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11408                         {
11409                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11410                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11411                                 if (!rsurface.texture->currentlayers->depthmask)
11412                                         GL_Color(c, 0, 0, 1.0f);
11413                                 else if (ent == r_refdef.scene.worldentity)
11414                                         GL_Color(c, c, c, 1.0f);
11415                                 else
11416                                         GL_Color(0, c, 0, 1.0f);
11417                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11418                                 RSurf_DrawBatch();
11419                         }
11420                 }
11421                 rsurface.texture = NULL;
11422         }
11423
11424         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11425
11426 //      R_Mesh_ResetTextureState();
11427         R_SetupShader_Generic_NoTexture(false, false);
11428         GL_DepthRange(0, 1);
11429         GL_DepthTest(!r_showdisabledepthtest.integer);
11430         GL_DepthMask(false);
11431         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11432
11433         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11434         {
11435                 int triangleindex;
11436                 int bihleafindex;
11437                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11438                 const q3mbrush_t *brush;
11439                 const bih_t *bih = &model->collision_bih;
11440                 const bih_leaf_t *bihleaf;
11441                 float vertex3f[3][3];
11442                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11443                 cullbox = false;
11444                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11445                 {
11446                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11447                                 continue;
11448                         switch (bihleaf->type)
11449                         {
11450                         case BIH_BRUSH:
11451                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11452                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11453                                 {
11454                                         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);
11455                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11456                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11457                                 }
11458                                 break;
11459                         case BIH_COLLISIONTRIANGLE:
11460                                 triangleindex = bihleaf->itemindex;
11461                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11462                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11463                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11464                                 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);
11465                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11466                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11467                                 break;
11468                         case BIH_RENDERTRIANGLE:
11469                                 triangleindex = bihleaf->itemindex;
11470                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11471                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11472                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11473                                 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);
11474                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11475                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11476                                 break;
11477                         }
11478                 }
11479         }
11480
11481         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11482
11483 #ifndef USE_GLES2
11484         if (r_showtris.integer && qglPolygonMode)
11485         {
11486                 if (r_showdisabledepthtest.integer)
11487                 {
11488                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11489                         GL_DepthMask(false);
11490                 }
11491                 else
11492                 {
11493                         GL_BlendFunc(GL_ONE, GL_ZERO);
11494                         GL_DepthMask(true);
11495                 }
11496                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11497                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11498                 {
11499                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11500                                 continue;
11501                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11502                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11503                         {
11504                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11505                                 if (!rsurface.texture->currentlayers->depthmask)
11506                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11507                                 else if (ent == r_refdef.scene.worldentity)
11508                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11509                                 else
11510                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11511                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11512                                 RSurf_DrawBatch();
11513                         }
11514                 }
11515                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11516                 rsurface.texture = NULL;
11517         }
11518
11519         if (r_shownormals.value != 0 && qglBegin)
11520         {
11521                 if (r_showdisabledepthtest.integer)
11522                 {
11523                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11524                         GL_DepthMask(false);
11525                 }
11526                 else
11527                 {
11528                         GL_BlendFunc(GL_ONE, GL_ZERO);
11529                         GL_DepthMask(true);
11530                 }
11531                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11532                 {
11533                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11534                                 continue;
11535                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11536                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11537                         {
11538                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11539                                 qglBegin(GL_LINES);
11540                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11541                                 {
11542                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11543                                         {
11544                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11545                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11546                                                 qglVertex3f(v[0], v[1], v[2]);
11547                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11548                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11549                                                 qglVertex3f(v[0], v[1], v[2]);
11550                                         }
11551                                 }
11552                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11553                                 {
11554                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11555                                         {
11556                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11557                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11558                                                 qglVertex3f(v[0], v[1], v[2]);
11559                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11560                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11561                                                 qglVertex3f(v[0], v[1], v[2]);
11562                                         }
11563                                 }
11564                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11565                                 {
11566                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11567                                         {
11568                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11569                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11570                                                 qglVertex3f(v[0], v[1], v[2]);
11571                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11572                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11573                                                 qglVertex3f(v[0], v[1], v[2]);
11574                                         }
11575                                 }
11576                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11577                                 {
11578                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11579                                         {
11580                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11581                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11582                                                 qglVertex3f(v[0], v[1], v[2]);
11583                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11584                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11585                                                 qglVertex3f(v[0], v[1], v[2]);
11586                                         }
11587                                 }
11588                                 qglEnd();
11589                                 CHECKGLERROR
11590                         }
11591                 }
11592                 rsurface.texture = NULL;
11593         }
11594 #endif
11595 }
11596
11597 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11598 int r_maxsurfacelist = 0;
11599 const msurface_t **r_surfacelist = NULL;
11600 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11601 {
11602         int i, j, endj, flagsmask;
11603         dp_model_t *model = r_refdef.scene.worldmodel;
11604         msurface_t *surfaces;
11605         unsigned char *update;
11606         int numsurfacelist = 0;
11607         if (model == NULL)
11608                 return;
11609
11610         if (r_maxsurfacelist < model->num_surfaces)
11611         {
11612                 r_maxsurfacelist = model->num_surfaces;
11613                 if (r_surfacelist)
11614                         Mem_Free((msurface_t**)r_surfacelist);
11615                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11616         }
11617
11618         RSurf_ActiveWorldEntity();
11619
11620         surfaces = model->data_surfaces;
11621         update = model->brushq1.lightmapupdateflags;
11622
11623         // update light styles on this submodel
11624         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11625         {
11626                 model_brush_lightstyleinfo_t *style;
11627                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11628                 {
11629                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11630                         {
11631                                 int *list = style->surfacelist;
11632                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11633                                 for (j = 0;j < style->numsurfaces;j++)
11634                                         update[list[j]] = true;
11635                         }
11636                 }
11637         }
11638
11639         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11640
11641         if (debug)
11642         {
11643                 R_DrawDebugModel();
11644                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11645                 return;
11646         }
11647
11648         rsurface.lightmaptexture = NULL;
11649         rsurface.deluxemaptexture = NULL;
11650         rsurface.uselightmaptexture = false;
11651         rsurface.texture = NULL;
11652         rsurface.rtlight = NULL;
11653         numsurfacelist = 0;
11654         // add visible surfaces to draw list
11655         for (i = 0;i < model->nummodelsurfaces;i++)
11656         {
11657                 j = model->sortedmodelsurfaces[i];
11658                 if (r_refdef.viewcache.world_surfacevisible[j])
11659                         r_surfacelist[numsurfacelist++] = surfaces + j;
11660         }
11661         // update lightmaps if needed
11662         if (model->brushq1.firstrender)
11663         {
11664                 model->brushq1.firstrender = false;
11665                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11666                         if (update[j])
11667                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11668         }
11669         else if (update)
11670         {
11671                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11672                         if (r_refdef.viewcache.world_surfacevisible[j])
11673                                 if (update[j])
11674                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11675         }
11676         // don't do anything if there were no surfaces
11677         if (!numsurfacelist)
11678         {
11679                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11680                 return;
11681         }
11682         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11683
11684         // add to stats if desired
11685         if (r_speeds.integer && !skysurfaces && !depthonly)
11686         {
11687                 r_refdef.stats.world_surfaces += numsurfacelist;
11688                 for (j = 0;j < numsurfacelist;j++)
11689                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11690         }
11691
11692         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11693 }
11694
11695 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11696 {
11697         int i, j, endj, flagsmask;
11698         dp_model_t *model = ent->model;
11699         msurface_t *surfaces;
11700         unsigned char *update;
11701         int numsurfacelist = 0;
11702         if (model == NULL)
11703                 return;
11704
11705         if (r_maxsurfacelist < model->num_surfaces)
11706         {
11707                 r_maxsurfacelist = model->num_surfaces;
11708                 if (r_surfacelist)
11709                         Mem_Free((msurface_t **)r_surfacelist);
11710                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11711         }
11712
11713         // if the model is static it doesn't matter what value we give for
11714         // wantnormals and wanttangents, so this logic uses only rules applicable
11715         // to a model, knowing that they are meaningless otherwise
11716         if (ent == r_refdef.scene.worldentity)
11717                 RSurf_ActiveWorldEntity();
11718         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11719                 RSurf_ActiveModelEntity(ent, false, false, false);
11720         else if (prepass)
11721                 RSurf_ActiveModelEntity(ent, true, true, true);
11722         else if (depthonly)
11723         {
11724                 switch (vid.renderpath)
11725                 {
11726                 case RENDERPATH_GL20:
11727                 case RENDERPATH_D3D9:
11728                 case RENDERPATH_D3D10:
11729                 case RENDERPATH_D3D11:
11730                 case RENDERPATH_SOFT:
11731                 case RENDERPATH_GLES2:
11732                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11733                         break;
11734                 case RENDERPATH_GL11:
11735                 case RENDERPATH_GL13:
11736                 case RENDERPATH_GLES1:
11737                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11738                         break;
11739                 }
11740         }
11741         else
11742         {
11743                 switch (vid.renderpath)
11744                 {
11745                 case RENDERPATH_GL20:
11746                 case RENDERPATH_D3D9:
11747                 case RENDERPATH_D3D10:
11748                 case RENDERPATH_D3D11:
11749                 case RENDERPATH_SOFT:
11750                 case RENDERPATH_GLES2:
11751                         RSurf_ActiveModelEntity(ent, true, true, false);
11752                         break;
11753                 case RENDERPATH_GL11:
11754                 case RENDERPATH_GL13:
11755                 case RENDERPATH_GLES1:
11756                         RSurf_ActiveModelEntity(ent, true, false, false);
11757                         break;
11758                 }
11759         }
11760
11761         surfaces = model->data_surfaces;
11762         update = model->brushq1.lightmapupdateflags;
11763
11764         // update light styles
11765         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11766         {
11767                 model_brush_lightstyleinfo_t *style;
11768                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11769                 {
11770                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11771                         {
11772                                 int *list = style->surfacelist;
11773                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11774                                 for (j = 0;j < style->numsurfaces;j++)
11775                                         update[list[j]] = true;
11776                         }
11777                 }
11778         }
11779
11780         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11781
11782         if (debug)
11783         {
11784                 R_DrawDebugModel();
11785                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11786                 return;
11787         }
11788
11789         rsurface.lightmaptexture = NULL;
11790         rsurface.deluxemaptexture = NULL;
11791         rsurface.uselightmaptexture = false;
11792         rsurface.texture = NULL;
11793         rsurface.rtlight = NULL;
11794         numsurfacelist = 0;
11795         // add visible surfaces to draw list
11796         for (i = 0;i < model->nummodelsurfaces;i++)
11797                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11798         // don't do anything if there were no surfaces
11799         if (!numsurfacelist)
11800         {
11801                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11802                 return;
11803         }
11804         // update lightmaps if needed
11805         if (update)
11806         {
11807                 int updated = 0;
11808                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11809                 {
11810                         if (update[j])
11811                         {
11812                                 updated++;
11813                                 R_BuildLightMap(ent, surfaces + j);
11814                         }
11815                 }
11816         }
11817         if (update)
11818                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11819                         if (update[j])
11820                                 R_BuildLightMap(ent, surfaces + j);
11821         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11822
11823         // add to stats if desired
11824         if (r_speeds.integer && !skysurfaces && !depthonly)
11825         {
11826                 r_refdef.stats.entities_surfaces += numsurfacelist;
11827                 for (j = 0;j < numsurfacelist;j++)
11828                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11829         }
11830
11831         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11832 }
11833
11834 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11835 {
11836         static texture_t texture;
11837         static msurface_t surface;
11838         const msurface_t *surfacelist = &surface;
11839
11840         // fake enough texture and surface state to render this geometry
11841
11842         texture.update_lastrenderframe = -1; // regenerate this texture
11843         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11844         texture.currentskinframe = skinframe;
11845         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11846         texture.offsetmapping = OFFSETMAPPING_OFF;
11847         texture.offsetscale = 1;
11848         texture.specularscalemod = 1;
11849         texture.specularpowermod = 1;
11850
11851         surface.texture = &texture;
11852         surface.num_triangles = numtriangles;
11853         surface.num_firsttriangle = firsttriangle;
11854         surface.num_vertices = numvertices;
11855         surface.num_firstvertex = firstvertex;
11856
11857         // now render it
11858         rsurface.texture = R_GetCurrentTexture(surface.texture);
11859         rsurface.lightmaptexture = NULL;
11860         rsurface.deluxemaptexture = NULL;
11861         rsurface.uselightmaptexture = false;
11862         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11863 }
11864
11865 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)
11866 {
11867         static msurface_t surface;
11868         const msurface_t *surfacelist = &surface;
11869
11870         // fake enough texture and surface state to render this geometry
11871         surface.texture = texture;
11872         surface.num_triangles = numtriangles;
11873         surface.num_firsttriangle = firsttriangle;
11874         surface.num_vertices = numvertices;
11875         surface.num_firstvertex = firstvertex;
11876
11877         // now render it
11878         rsurface.texture = R_GetCurrentTexture(surface.texture);
11879         rsurface.lightmaptexture = NULL;
11880         rsurface.deluxemaptexture = NULL;
11881         rsurface.uselightmaptexture = false;
11882         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11883 }