]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix bugs with CSQC clearscene function - it now restores the view to
[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
186 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
187 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
188 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
189 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
190
191 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
192 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
193 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
194 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
195 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
196 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
197 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
198
199 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
200 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
201 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
202 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
203 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
204 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
205 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
208 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
209 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
210 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
211
212 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"};
213
214 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"};
215
216 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
217
218 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
219
220 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
221 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"};
222
223 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."};
224
225 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)"};
226
227 extern cvar_t v_glslgamma;
228 extern cvar_t v_glslgamma_2d;
229
230 extern qboolean v_flipped_state;
231
232 static struct r_bloomstate_s
233 {
234         qboolean enabled;
235         qboolean hdr;
236
237         int bloomwidth, bloomheight;
238
239         textype_t texturetype;
240         int viewfbo; // used to check if r_viewfbo cvar has changed
241
242         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
243         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
244         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
245
246         int screentexturewidth, screentextureheight;
247         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
248
249         int bloomtexturewidth, bloomtextureheight;
250         rtexture_t *texture_bloom;
251
252         // arrays for rendering the screen passes
253         float screentexcoord2f[8];
254         float bloomtexcoord2f[8];
255         float offsettexcoord2f[8];
256
257         r_viewport_t viewport;
258 }
259 r_bloomstate;
260
261 r_waterstate_t r_waterstate;
262
263 /// shadow volume bsp struct with automatically growing nodes buffer
264 svbsp_t r_svbsp;
265
266 rtexture_t *r_texture_blanknormalmap;
267 rtexture_t *r_texture_white;
268 rtexture_t *r_texture_grey128;
269 rtexture_t *r_texture_black;
270 rtexture_t *r_texture_notexture;
271 rtexture_t *r_texture_whitecube;
272 rtexture_t *r_texture_normalizationcube;
273 rtexture_t *r_texture_fogattenuation;
274 rtexture_t *r_texture_fogheighttexture;
275 rtexture_t *r_texture_gammaramps;
276 unsigned int r_texture_gammaramps_serial;
277 //rtexture_t *r_texture_fogintensity;
278 rtexture_t *r_texture_reflectcube;
279
280 // TODO: hash lookups?
281 typedef struct cubemapinfo_s
282 {
283         char basename[64];
284         rtexture_t *texture;
285 }
286 cubemapinfo_t;
287
288 int r_texture_numcubemaps;
289 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
290
291 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
292 unsigned int r_numqueries;
293 unsigned int r_maxqueries;
294
295 typedef struct r_qwskincache_s
296 {
297         char name[MAX_QPATH];
298         skinframe_t *skinframe;
299 }
300 r_qwskincache_t;
301
302 static r_qwskincache_t *r_qwskincache;
303 static int r_qwskincache_size;
304
305 /// vertex coordinates for a quad that covers the screen exactly
306 extern const float r_screenvertex3f[12];
307 extern const float r_d3dscreenvertex3f[12];
308 const float r_screenvertex3f[12] =
309 {
310         0, 0, 0,
311         1, 0, 0,
312         1, 1, 0,
313         0, 1, 0
314 };
315 const float r_d3dscreenvertex3f[12] =
316 {
317         0, 1, 0,
318         1, 1, 0,
319         1, 0, 0,
320         0, 0, 0
321 };
322
323 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
324 {
325         int i;
326         for (i = 0;i < verts;i++)
327         {
328                 out[0] = in[0] * r;
329                 out[1] = in[1] * g;
330                 out[2] = in[2] * b;
331                 out[3] = in[3];
332                 in += 4;
333                 out += 4;
334         }
335 }
336
337 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
338 {
339         int i;
340         for (i = 0;i < verts;i++)
341         {
342                 out[0] = r;
343                 out[1] = g;
344                 out[2] = b;
345                 out[3] = a;
346                 out += 4;
347         }
348 }
349
350 // FIXME: move this to client?
351 void FOG_clear(void)
352 {
353         if (gamemode == GAME_NEHAHRA)
354         {
355                 Cvar_Set("gl_fogenable", "0");
356                 Cvar_Set("gl_fogdensity", "0.2");
357                 Cvar_Set("gl_fogred", "0.3");
358                 Cvar_Set("gl_foggreen", "0.3");
359                 Cvar_Set("gl_fogblue", "0.3");
360         }
361         r_refdef.fog_density = 0;
362         r_refdef.fog_red = 0;
363         r_refdef.fog_green = 0;
364         r_refdef.fog_blue = 0;
365         r_refdef.fog_alpha = 1;
366         r_refdef.fog_start = 0;
367         r_refdef.fog_end = 16384;
368         r_refdef.fog_height = 1<<30;
369         r_refdef.fog_fadedepth = 128;
370         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
371 }
372
373 static void R_BuildBlankTextures(void)
374 {
375         unsigned char data[4];
376         data[2] = 128; // normal X
377         data[1] = 128; // normal Y
378         data[0] = 255; // normal Z
379         data[3] = 255; // height
380         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 255;
382         data[1] = 255;
383         data[2] = 255;
384         data[3] = 255;
385         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 128;
387         data[1] = 128;
388         data[2] = 128;
389         data[3] = 255;
390         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391         data[0] = 0;
392         data[1] = 0;
393         data[2] = 0;
394         data[3] = 255;
395         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildNoTexture(void)
399 {
400         int x, y;
401         unsigned char pix[16][16][4];
402         // this makes a light grey/dark grey checkerboard texture
403         for (y = 0;y < 16;y++)
404         {
405                 for (x = 0;x < 16;x++)
406                 {
407                         if ((y < 8) ^ (x < 8))
408                         {
409                                 pix[y][x][0] = 128;
410                                 pix[y][x][1] = 128;
411                                 pix[y][x][2] = 128;
412                                 pix[y][x][3] = 255;
413                         }
414                         else
415                         {
416                                 pix[y][x][0] = 64;
417                                 pix[y][x][1] = 64;
418                                 pix[y][x][2] = 64;
419                                 pix[y][x][3] = 255;
420                         }
421                 }
422         }
423         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
424 }
425
426 static void R_BuildWhiteCube(void)
427 {
428         unsigned char data[6*1*1*4];
429         memset(data, 255, sizeof(data));
430         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
431 }
432
433 static void R_BuildNormalizationCube(void)
434 {
435         int x, y, side;
436         vec3_t v;
437         vec_t s, t, intensity;
438 #define NORMSIZE 64
439         unsigned char *data;
440         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
441         for (side = 0;side < 6;side++)
442         {
443                 for (y = 0;y < NORMSIZE;y++)
444                 {
445                         for (x = 0;x < NORMSIZE;x++)
446                         {
447                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
448                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
449                                 switch(side)
450                                 {
451                                 default:
452                                 case 0:
453                                         v[0] = 1;
454                                         v[1] = -t;
455                                         v[2] = -s;
456                                         break;
457                                 case 1:
458                                         v[0] = -1;
459                                         v[1] = -t;
460                                         v[2] = s;
461                                         break;
462                                 case 2:
463                                         v[0] = s;
464                                         v[1] = 1;
465                                         v[2] = t;
466                                         break;
467                                 case 3:
468                                         v[0] = s;
469                                         v[1] = -1;
470                                         v[2] = -t;
471                                         break;
472                                 case 4:
473                                         v[0] = s;
474                                         v[1] = -t;
475                                         v[2] = 1;
476                                         break;
477                                 case 5:
478                                         v[0] = -s;
479                                         v[1] = -t;
480                                         v[2] = -1;
481                                         break;
482                                 }
483                                 intensity = 127.0f / sqrt(DotProduct(v, v));
484                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
485                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
486                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
487                                 data[((side*64+y)*64+x)*4+3] = 255;
488                         }
489                 }
490         }
491         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
492         Mem_Free(data);
493 }
494
495 static void R_BuildFogTexture(void)
496 {
497         int x, b;
498 #define FOGWIDTH 256
499         unsigned char data1[FOGWIDTH][4];
500         //unsigned char data2[FOGWIDTH][4];
501         double d, r, alpha;
502
503         r_refdef.fogmasktable_start = r_refdef.fog_start;
504         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
505         r_refdef.fogmasktable_range = r_refdef.fogrange;
506         r_refdef.fogmasktable_density = r_refdef.fog_density;
507
508         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
509         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
510         {
511                 d = (x * r - r_refdef.fogmasktable_start);
512                 if(developer_extra.integer)
513                         Con_DPrintf("%f ", d);
514                 d = max(0, d);
515                 if (r_fog_exp2.integer)
516                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
517                 else
518                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
519                 if(developer_extra.integer)
520                         Con_DPrintf(" : %f ", alpha);
521                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
522                 if(developer_extra.integer)
523                         Con_DPrintf(" = %f\n", alpha);
524                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
525         }
526
527         for (x = 0;x < FOGWIDTH;x++)
528         {
529                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
530                 data1[x][0] = b;
531                 data1[x][1] = b;
532                 data1[x][2] = b;
533                 data1[x][3] = 255;
534                 //data2[x][0] = 255 - b;
535                 //data2[x][1] = 255 - b;
536                 //data2[x][2] = 255 - b;
537                 //data2[x][3] = 255;
538         }
539         if (r_texture_fogattenuation)
540         {
541                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543         }
544         else
545         {
546                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
547                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
548         }
549 }
550
551 static void R_BuildFogHeightTexture(void)
552 {
553         unsigned char *inpixels;
554         int size;
555         int x;
556         int y;
557         int j;
558         float c[4];
559         float f;
560         inpixels = NULL;
561         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
562         if (r_refdef.fogheighttexturename[0])
563                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
564         if (!inpixels)
565         {
566                 r_refdef.fog_height_tablesize = 0;
567                 if (r_texture_fogheighttexture)
568                         R_FreeTexture(r_texture_fogheighttexture);
569                 r_texture_fogheighttexture = NULL;
570                 if (r_refdef.fog_height_table2d)
571                         Mem_Free(r_refdef.fog_height_table2d);
572                 r_refdef.fog_height_table2d = NULL;
573                 if (r_refdef.fog_height_table1d)
574                         Mem_Free(r_refdef.fog_height_table1d);
575                 r_refdef.fog_height_table1d = NULL;
576                 return;
577         }
578         size = image_width;
579         r_refdef.fog_height_tablesize = size;
580         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
581         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
582         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
583         Mem_Free(inpixels);
584         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
585         // average fog color table accounting for every fog layer between a point
586         // and the camera.  (Note: attenuation is handled separately!)
587         for (y = 0;y < size;y++)
588         {
589                 for (x = 0;x < size;x++)
590                 {
591                         Vector4Clear(c);
592                         f = 0;
593                         if (x < y)
594                         {
595                                 for (j = x;j <= y;j++)
596                                 {
597                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598                                         f++;
599                                 }
600                         }
601                         else
602                         {
603                                 for (j = x;j >= y;j--)
604                                 {
605                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606                                         f++;
607                                 }
608                         }
609                         f = 1.0f / f;
610                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
613                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
614                 }
615         }
616         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
617 }
618
619 //=======================================================================================================================================================
620
621 static const char *builtinshaderstring =
622 #include "shader_glsl.h"
623 ;
624
625 const char *builtinhlslshaderstring =
626 #include "shader_hlsl.h"
627 ;
628
629 char *glslshaderstring = NULL;
630 char *hlslshaderstring = NULL;
631
632 //=======================================================================================================================================================
633
634 typedef struct shaderpermutationinfo_s
635 {
636         const char *pretext;
637         const char *name;
638 }
639 shaderpermutationinfo_t;
640
641 typedef struct shadermodeinfo_s
642 {
643         const char *vertexfilename;
644         const char *geometryfilename;
645         const char *fragmentfilename;
646         const char *pretext;
647         const char *name;
648 }
649 shadermodeinfo_t;
650
651 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
652 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
653 {
654         {"#define USEDIFFUSE\n", " diffuse"},
655         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
656         {"#define USEVIEWTINT\n", " viewtint"},
657         {"#define USECOLORMAPPING\n", " colormapping"},
658         {"#define USESATURATION\n", " saturation"},
659         {"#define USEFOGINSIDE\n", " foginside"},
660         {"#define USEFOGOUTSIDE\n", " fogoutside"},
661         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
662         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
663         {"#define USEGAMMARAMPS\n", " gammaramps"},
664         {"#define USECUBEFILTER\n", " cubefilter"},
665         {"#define USEGLOW\n", " glow"},
666         {"#define USEBLOOM\n", " bloom"},
667         {"#define USESPECULAR\n", " specular"},
668         {"#define USEPOSTPROCESSING\n", " postprocessing"},
669         {"#define USEREFLECTION\n", " reflection"},
670         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
671         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
672         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
673         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
674         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
675         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
676         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
677         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
678         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
679         {"#define USEALPHAKILL\n", " alphakill"},
680         {"#define USEREFLECTCUBE\n", " reflectcube"},
681         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
682         {"#define USEBOUNCEGRID\n", " bouncegrid"},
683         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
684         {"#define USETRIPPY\n", " trippy"},
685 };
686
687 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
688 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
689 {
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
706         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
707         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
708 };
709
710 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
711 {
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
728         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
729         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
730 };
731
732 struct r_glsl_permutation_s;
733 typedef struct r_glsl_permutation_s
734 {
735         /// hash lookup data
736         struct r_glsl_permutation_s *hashnext;
737         unsigned int mode;
738         unsigned int permutation;
739
740         /// indicates if we have tried compiling this permutation already
741         qboolean compiled;
742         /// 0 if compilation failed
743         int program;
744         // texture units assigned to each detected uniform
745         int tex_Texture_First;
746         int tex_Texture_Second;
747         int tex_Texture_GammaRamps;
748         int tex_Texture_Normal;
749         int tex_Texture_Color;
750         int tex_Texture_Gloss;
751         int tex_Texture_Glow;
752         int tex_Texture_SecondaryNormal;
753         int tex_Texture_SecondaryColor;
754         int tex_Texture_SecondaryGloss;
755         int tex_Texture_SecondaryGlow;
756         int tex_Texture_Pants;
757         int tex_Texture_Shirt;
758         int tex_Texture_FogHeightTexture;
759         int tex_Texture_FogMask;
760         int tex_Texture_Lightmap;
761         int tex_Texture_Deluxemap;
762         int tex_Texture_Attenuation;
763         int tex_Texture_Cube;
764         int tex_Texture_Refraction;
765         int tex_Texture_Reflection;
766         int tex_Texture_ShadowMap2D;
767         int tex_Texture_CubeProjection;
768         int tex_Texture_ScreenDepth;
769         int tex_Texture_ScreenNormalMap;
770         int tex_Texture_ScreenDiffuse;
771         int tex_Texture_ScreenSpecular;
772         int tex_Texture_ReflectMask;
773         int tex_Texture_ReflectCube;
774         int tex_Texture_BounceGrid;
775         /// locations of detected uniforms in program object, or -1 if not found
776         int loc_Texture_First;
777         int loc_Texture_Second;
778         int loc_Texture_GammaRamps;
779         int loc_Texture_Normal;
780         int loc_Texture_Color;
781         int loc_Texture_Gloss;
782         int loc_Texture_Glow;
783         int loc_Texture_SecondaryNormal;
784         int loc_Texture_SecondaryColor;
785         int loc_Texture_SecondaryGloss;
786         int loc_Texture_SecondaryGlow;
787         int loc_Texture_Pants;
788         int loc_Texture_Shirt;
789         int loc_Texture_FogHeightTexture;
790         int loc_Texture_FogMask;
791         int loc_Texture_Lightmap;
792         int loc_Texture_Deluxemap;
793         int loc_Texture_Attenuation;
794         int loc_Texture_Cube;
795         int loc_Texture_Refraction;
796         int loc_Texture_Reflection;
797         int loc_Texture_ShadowMap2D;
798         int loc_Texture_CubeProjection;
799         int loc_Texture_ScreenDepth;
800         int loc_Texture_ScreenNormalMap;
801         int loc_Texture_ScreenDiffuse;
802         int loc_Texture_ScreenSpecular;
803         int loc_Texture_ReflectMask;
804         int loc_Texture_ReflectCube;
805         int loc_Texture_BounceGrid;
806         int loc_Alpha;
807         int loc_BloomBlur_Parameters;
808         int loc_ClientTime;
809         int loc_Color_Ambient;
810         int loc_Color_Diffuse;
811         int loc_Color_Specular;
812         int loc_Color_Glow;
813         int loc_Color_Pants;
814         int loc_Color_Shirt;
815         int loc_DeferredColor_Ambient;
816         int loc_DeferredColor_Diffuse;
817         int loc_DeferredColor_Specular;
818         int loc_DeferredMod_Diffuse;
819         int loc_DeferredMod_Specular;
820         int loc_DistortScaleRefractReflect;
821         int loc_EyePosition;
822         int loc_FogColor;
823         int loc_FogHeightFade;
824         int loc_FogPlane;
825         int loc_FogPlaneViewDist;
826         int loc_FogRangeRecip;
827         int loc_LightColor;
828         int loc_LightDir;
829         int loc_LightPosition;
830         int loc_OffsetMapping_ScaleSteps;
831         int loc_OffsetMapping_LodDistance;
832         int loc_OffsetMapping_Bias;
833         int loc_PixelSize;
834         int loc_ReflectColor;
835         int loc_ReflectFactor;
836         int loc_ReflectOffset;
837         int loc_RefractColor;
838         int loc_Saturation;
839         int loc_ScreenCenterRefractReflect;
840         int loc_ScreenScaleRefractReflect;
841         int loc_ScreenToDepth;
842         int loc_ShadowMap_Parameters;
843         int loc_ShadowMap_TextureScale;
844         int loc_SpecularPower;
845         int loc_UserVec1;
846         int loc_UserVec2;
847         int loc_UserVec3;
848         int loc_UserVec4;
849         int loc_ViewTintColor;
850         int loc_ViewToLight;
851         int loc_ModelToLight;
852         int loc_TexMatrix;
853         int loc_BackgroundTexMatrix;
854         int loc_ModelViewProjectionMatrix;
855         int loc_ModelViewMatrix;
856         int loc_PixelToScreenTexCoord;
857         int loc_ModelToReflectCube;
858         int loc_ShadowMapMatrix;
859         int loc_BloomColorSubtract;
860         int loc_NormalmapScrollBlend;
861         int loc_BounceGridMatrix;
862         int loc_BounceGridIntensity;
863 }
864 r_glsl_permutation_t;
865
866 #define SHADERPERMUTATION_HASHSIZE 256
867
868
869 // non-degradable "lightweight" shader parameters to keep the permutations simpler
870 // these can NOT degrade! only use for simple stuff
871 enum
872 {
873         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
874         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
875         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
877         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
878         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
879         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
880         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
881 };
882 #define SHADERSTATICPARMS_COUNT 8
883
884 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
885 static int shaderstaticparms_count = 0;
886
887 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
888 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
889 qboolean R_CompileShader_CheckStaticParms(void)
890 {
891         static int r_compileshader_staticparms_save[1];
892         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
893         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
894
895         // detect all
896         if (r_glsl_saturation_redcompensate.integer)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
898         if (r_glsl_vertextextureblend_usebothalphas.integer)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
900         if (r_shadow_glossexact.integer)
901                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
902         if (r_glsl_postprocess.integer)
903         {
904                 if (r_glsl_postprocess_uservec1_enable.integer)
905                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
906                 if (r_glsl_postprocess_uservec2_enable.integer)
907                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
908                 if (r_glsl_postprocess_uservec3_enable.integer)
909                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
910                 if (r_glsl_postprocess_uservec4_enable.integer)
911                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
912         }
913         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
914                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
915         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
916 }
917
918 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
919         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
920                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
921         else \
922                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
923 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
924 {
925         shaderstaticparms_count = 0;
926
927         // emit all
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
936 }
937
938 /// information about each possible shader permutation
939 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
940 /// currently selected permutation
941 r_glsl_permutation_t *r_glsl_permutation;
942 /// storage for permutations linked in the hash table
943 memexpandablearray_t r_glsl_permutationarray;
944
945 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
946 {
947         //unsigned int hashdepth = 0;
948         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
949         r_glsl_permutation_t *p;
950         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
951         {
952                 if (p->mode == mode && p->permutation == permutation)
953                 {
954                         //if (hashdepth > 10)
955                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956                         return p;
957                 }
958                 //hashdepth++;
959         }
960         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
961         p->mode = mode;
962         p->permutation = permutation;
963         p->hashnext = r_glsl_permutationhash[mode][hashindex];
964         r_glsl_permutationhash[mode][hashindex] = p;
965         //if (hashdepth > 10)
966         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
967         return p;
968 }
969
970 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
971 {
972         char *shaderstring;
973         if (!filename || !filename[0])
974                 return NULL;
975         if (!strcmp(filename, "glsl/default.glsl"))
976         {
977                 if (!glslshaderstring)
978                 {
979                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
980                         if (glslshaderstring)
981                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
982                         else
983                                 glslshaderstring = (char *)builtinshaderstring;
984                 }
985                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
986                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
987                 return shaderstring;
988         }
989         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
990         if (shaderstring)
991         {
992                 if (printfromdisknotice)
993                         Con_DPrintf("from disk %s... ", filename);
994                 return shaderstring;
995         }
996         return shaderstring;
997 }
998
999 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1000 {
1001         int i;
1002         int sampler;
1003         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1004         char *vertexstring, *geometrystring, *fragmentstring;
1005         char permutationname[256];
1006         int vertstrings_count = 0;
1007         int geomstrings_count = 0;
1008         int fragstrings_count = 0;
1009         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1010         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1011         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1012
1013         if (p->compiled)
1014                 return;
1015         p->compiled = true;
1016         p->program = 0;
1017
1018         permutationname[0] = 0;
1019         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1020         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1021         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1022
1023         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1024
1025         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1026         if(vid.support.gl20shaders130)
1027         {
1028                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1029                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1030                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1031                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1032                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1033                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1034         }
1035
1036         // the first pretext is which type of shader to compile as
1037         // (later these will all be bound together as a program object)
1038         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1039         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1040         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1041
1042         // the second pretext is the mode (for example a light source)
1043         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1044         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1045         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1046         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1047
1048         // now add all the permutation pretexts
1049         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1050         {
1051                 if (permutation & (1<<i))
1052                 {
1053                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1056                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1057                 }
1058                 else
1059                 {
1060                         // keep line numbers correct
1061                         vertstrings_list[vertstrings_count++] = "\n";
1062                         geomstrings_list[geomstrings_count++] = "\n";
1063                         fragstrings_list[fragstrings_count++] = "\n";
1064                 }
1065         }
1066
1067         // add static parms
1068         R_CompileShader_AddStaticParms(mode, permutation);
1069         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1070         vertstrings_count += shaderstaticparms_count;
1071         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1072         geomstrings_count += shaderstaticparms_count;
1073         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1074         fragstrings_count += shaderstaticparms_count;
1075
1076         // now append the shader text itself
1077         vertstrings_list[vertstrings_count++] = vertexstring;
1078         geomstrings_list[geomstrings_count++] = geometrystring;
1079         fragstrings_list[fragstrings_count++] = fragmentstring;
1080
1081         // if any sources were NULL, clear the respective list
1082         if (!vertexstring)
1083                 vertstrings_count = 0;
1084         if (!geometrystring)
1085                 geomstrings_count = 0;
1086         if (!fragmentstring)
1087                 fragstrings_count = 0;
1088
1089         // compile the shader program
1090         if (vertstrings_count + geomstrings_count + fragstrings_count)
1091                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1092         if (p->program)
1093         {
1094                 CHECKGLERROR
1095                 qglUseProgram(p->program);CHECKGLERROR
1096                 // look up all the uniform variable names we care about, so we don't
1097                 // have to look them up every time we set them
1098
1099                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1100                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1101                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1102                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1103                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1104                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1105                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1106                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1107                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1108                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1109                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1110                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1111                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1112                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1113                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1114                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1115                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1116                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1117                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1118                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1119                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1120                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1121                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1122                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1123                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1124                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1125                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1126                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1127                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1128                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1129                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1130                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1131                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1132                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1133                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1134                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1135                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1136                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1137                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1138                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1139                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1140                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1141                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1142                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1143                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1144                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1145                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1146                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1147                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1148                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1149                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1150                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1151                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1152                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1153                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1154                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1155                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1156                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1157                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1158                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1159                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1160                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1161                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1162                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1163                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1164                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1165                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1166                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1167                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1168                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1169                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1170                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1171                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1172                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1173                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1174                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1175                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1176                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1177                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1178                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1179                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1180                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1181                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1182                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1183                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1184                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1185                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1186                 // initialize the samplers to refer to the texture units we use
1187                 p->tex_Texture_First = -1;
1188                 p->tex_Texture_Second = -1;
1189                 p->tex_Texture_GammaRamps = -1;
1190                 p->tex_Texture_Normal = -1;
1191                 p->tex_Texture_Color = -1;
1192                 p->tex_Texture_Gloss = -1;
1193                 p->tex_Texture_Glow = -1;
1194                 p->tex_Texture_SecondaryNormal = -1;
1195                 p->tex_Texture_SecondaryColor = -1;
1196                 p->tex_Texture_SecondaryGloss = -1;
1197                 p->tex_Texture_SecondaryGlow = -1;
1198                 p->tex_Texture_Pants = -1;
1199                 p->tex_Texture_Shirt = -1;
1200                 p->tex_Texture_FogHeightTexture = -1;
1201                 p->tex_Texture_FogMask = -1;
1202                 p->tex_Texture_Lightmap = -1;
1203                 p->tex_Texture_Deluxemap = -1;
1204                 p->tex_Texture_Attenuation = -1;
1205                 p->tex_Texture_Cube = -1;
1206                 p->tex_Texture_Refraction = -1;
1207                 p->tex_Texture_Reflection = -1;
1208                 p->tex_Texture_ShadowMap2D = -1;
1209                 p->tex_Texture_CubeProjection = -1;
1210                 p->tex_Texture_ScreenDepth = -1;
1211                 p->tex_Texture_ScreenNormalMap = -1;
1212                 p->tex_Texture_ScreenDiffuse = -1;
1213                 p->tex_Texture_ScreenSpecular = -1;
1214                 p->tex_Texture_ReflectMask = -1;
1215                 p->tex_Texture_ReflectCube = -1;
1216                 p->tex_Texture_BounceGrid = -1;
1217                 sampler = 0;
1218                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1219                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1220                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1221                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1222                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1223                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1224                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1226                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1227                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1228                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1229                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1230                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1231                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1232                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1233                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1234                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1235                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1236                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1237                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1238                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1239                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1240                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1242                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1243                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1244                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1245                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1246                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1247                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1248                 CHECKGLERROR
1249                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1250         }
1251         else
1252                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1253
1254         // free the strings
1255         if (vertexstring)
1256                 Mem_Free(vertexstring);
1257         if (geometrystring)
1258                 Mem_Free(geometrystring);
1259         if (fragmentstring)
1260                 Mem_Free(fragmentstring);
1261 }
1262
1263 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1264 {
1265         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1266         if (r_glsl_permutation != perm)
1267         {
1268                 r_glsl_permutation = perm;
1269                 if (!r_glsl_permutation->program)
1270                 {
1271                         if (!r_glsl_permutation->compiled)
1272                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1273                         if (!r_glsl_permutation->program)
1274                         {
1275                                 // remove features until we find a valid permutation
1276                                 int i;
1277                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1278                                 {
1279                                         // reduce i more quickly whenever it would not remove any bits
1280                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1281                                         if (!(permutation & j))
1282                                                 continue;
1283                                         permutation -= j;
1284                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1285                                         if (!r_glsl_permutation->compiled)
1286                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1287                                         if (r_glsl_permutation->program)
1288                                                 break;
1289                                 }
1290                                 if (i >= SHADERPERMUTATION_COUNT)
1291                                 {
1292                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1293                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1294                                         qglUseProgram(0);CHECKGLERROR
1295                                         return; // no bit left to clear, entire mode is broken
1296                                 }
1297                         }
1298                 }
1299                 CHECKGLERROR
1300                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1301         }
1302         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1303         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1304         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1305 }
1306
1307 #ifdef SUPPORTD3D
1308
1309 #ifdef SUPPORTD3D
1310 #include <d3d9.h>
1311 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1312 extern D3DCAPS9 vid_d3d9caps;
1313 #endif
1314
1315 struct r_hlsl_permutation_s;
1316 typedef struct r_hlsl_permutation_s
1317 {
1318         /// hash lookup data
1319         struct r_hlsl_permutation_s *hashnext;
1320         unsigned int mode;
1321         unsigned int permutation;
1322
1323         /// indicates if we have tried compiling this permutation already
1324         qboolean compiled;
1325         /// NULL if compilation failed
1326         IDirect3DVertexShader9 *vertexshader;
1327         IDirect3DPixelShader9 *pixelshader;
1328 }
1329 r_hlsl_permutation_t;
1330
1331 typedef enum D3DVSREGISTER_e
1332 {
1333         D3DVSREGISTER_TexMatrix = 0, // float4x4
1334         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1335         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1336         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1337         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1338         D3DVSREGISTER_ModelToLight = 20, // float4x4
1339         D3DVSREGISTER_EyePosition = 24,
1340         D3DVSREGISTER_FogPlane = 25,
1341         D3DVSREGISTER_LightDir = 26,
1342         D3DVSREGISTER_LightPosition = 27,
1343 }
1344 D3DVSREGISTER_t;
1345
1346 typedef enum D3DPSREGISTER_e
1347 {
1348         D3DPSREGISTER_Alpha = 0,
1349         D3DPSREGISTER_BloomBlur_Parameters = 1,
1350         D3DPSREGISTER_ClientTime = 2,
1351         D3DPSREGISTER_Color_Ambient = 3,
1352         D3DPSREGISTER_Color_Diffuse = 4,
1353         D3DPSREGISTER_Color_Specular = 5,
1354         D3DPSREGISTER_Color_Glow = 6,
1355         D3DPSREGISTER_Color_Pants = 7,
1356         D3DPSREGISTER_Color_Shirt = 8,
1357         D3DPSREGISTER_DeferredColor_Ambient = 9,
1358         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1359         D3DPSREGISTER_DeferredColor_Specular = 11,
1360         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1361         D3DPSREGISTER_DeferredMod_Specular = 13,
1362         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1363         D3DPSREGISTER_EyePosition = 15, // unused
1364         D3DPSREGISTER_FogColor = 16,
1365         D3DPSREGISTER_FogHeightFade = 17,
1366         D3DPSREGISTER_FogPlane = 18,
1367         D3DPSREGISTER_FogPlaneViewDist = 19,
1368         D3DPSREGISTER_FogRangeRecip = 20,
1369         D3DPSREGISTER_LightColor = 21,
1370         D3DPSREGISTER_LightDir = 22, // unused
1371         D3DPSREGISTER_LightPosition = 23,
1372         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1373         D3DPSREGISTER_PixelSize = 25,
1374         D3DPSREGISTER_ReflectColor = 26,
1375         D3DPSREGISTER_ReflectFactor = 27,
1376         D3DPSREGISTER_ReflectOffset = 28,
1377         D3DPSREGISTER_RefractColor = 29,
1378         D3DPSREGISTER_Saturation = 30,
1379         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1380         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1381         D3DPSREGISTER_ScreenToDepth = 33,
1382         D3DPSREGISTER_ShadowMap_Parameters = 34,
1383         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1384         D3DPSREGISTER_SpecularPower = 36,
1385         D3DPSREGISTER_UserVec1 = 37,
1386         D3DPSREGISTER_UserVec2 = 38,
1387         D3DPSREGISTER_UserVec3 = 39,
1388         D3DPSREGISTER_UserVec4 = 40,
1389         D3DPSREGISTER_ViewTintColor = 41,
1390         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1391         D3DPSREGISTER_BloomColorSubtract = 43,
1392         D3DPSREGISTER_ViewToLight = 44, // float4x4
1393         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1394         D3DPSREGISTER_NormalmapScrollBlend = 52,
1395         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1396         D3DPSREGISTER_OffsetMapping_Bias = 54,
1397         // next at 54
1398 }
1399 D3DPSREGISTER_t;
1400
1401 /// information about each possible shader permutation
1402 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1403 /// currently selected permutation
1404 r_hlsl_permutation_t *r_hlsl_permutation;
1405 /// storage for permutations linked in the hash table
1406 memexpandablearray_t r_hlsl_permutationarray;
1407
1408 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1409 {
1410         //unsigned int hashdepth = 0;
1411         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1412         r_hlsl_permutation_t *p;
1413         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1414         {
1415                 if (p->mode == mode && p->permutation == permutation)
1416                 {
1417                         //if (hashdepth > 10)
1418                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1419                         return p;
1420                 }
1421                 //hashdepth++;
1422         }
1423         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1424         p->mode = mode;
1425         p->permutation = permutation;
1426         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1427         r_hlsl_permutationhash[mode][hashindex] = p;
1428         //if (hashdepth > 10)
1429         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1430         return p;
1431 }
1432
1433 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1434 {
1435         char *shaderstring;
1436         if (!filename || !filename[0])
1437                 return NULL;
1438         if (!strcmp(filename, "hlsl/default.hlsl"))
1439         {
1440                 if (!hlslshaderstring)
1441                 {
1442                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1443                         if (hlslshaderstring)
1444                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1445                         else
1446                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1447                 }
1448                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1449                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1450                 return shaderstring;
1451         }
1452         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1453         if (shaderstring)
1454         {
1455                 if (printfromdisknotice)
1456                         Con_DPrintf("from disk %s... ", filename);
1457                 return shaderstring;
1458         }
1459         return shaderstring;
1460 }
1461
1462 #include <d3dx9.h>
1463 //#include <d3dx9shader.h>
1464 //#include <d3dx9mesh.h>
1465
1466 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1467 {
1468         DWORD *vsbin = NULL;
1469         DWORD *psbin = NULL;
1470         fs_offset_t vsbinsize;
1471         fs_offset_t psbinsize;
1472 //      IDirect3DVertexShader9 *vs = NULL;
1473 //      IDirect3DPixelShader9 *ps = NULL;
1474         ID3DXBuffer *vslog = NULL;
1475         ID3DXBuffer *vsbuffer = NULL;
1476         ID3DXConstantTable *vsconstanttable = NULL;
1477         ID3DXBuffer *pslog = NULL;
1478         ID3DXBuffer *psbuffer = NULL;
1479         ID3DXConstantTable *psconstanttable = NULL;
1480         int vsresult = 0;
1481         int psresult = 0;
1482         char temp[MAX_INPUTLINE];
1483         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1484         qboolean debugshader = gl_paranoid.integer != 0;
1485         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1486         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1487         if (!debugshader)
1488         {
1489                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1490                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1491         }
1492         if ((!vsbin && vertstring) || (!psbin && fragstring))
1493         {
1494                 const char* dllnames_d3dx9 [] =
1495                 {
1496                         "d3dx9_43.dll",
1497                         "d3dx9_42.dll",
1498                         "d3dx9_41.dll",
1499                         "d3dx9_40.dll",
1500                         "d3dx9_39.dll",
1501                         "d3dx9_38.dll",
1502                         "d3dx9_37.dll",
1503                         "d3dx9_36.dll",
1504                         "d3dx9_35.dll",
1505                         "d3dx9_34.dll",
1506                         "d3dx9_33.dll",
1507                         "d3dx9_32.dll",
1508                         "d3dx9_31.dll",
1509                         "d3dx9_30.dll",
1510                         "d3dx9_29.dll",
1511                         "d3dx9_28.dll",
1512                         "d3dx9_27.dll",
1513                         "d3dx9_26.dll",
1514                         "d3dx9_25.dll",
1515                         "d3dx9_24.dll",
1516                         NULL
1517                 };
1518                 dllhandle_t d3dx9_dll = NULL;
1519                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1520                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1521                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1522                 dllfunction_t d3dx9_dllfuncs[] =
1523                 {
1524                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1525                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1526                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1527                         {NULL, NULL}
1528                 };
1529                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1530                 {
1531                         DWORD shaderflags = 0;
1532                         if (debugshader)
1533                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1534                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1535                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1536                         if (vertstring && vertstring[0])
1537                         {
1538                                 if (debugshader)
1539                                 {
1540 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1541 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1542                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1543                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1544                                 }
1545                                 else
1546                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1547                                 if (vsbuffer)
1548                                 {
1549                                         vsbinsize = vsbuffer->GetBufferSize();
1550                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1551                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1552                                         vsbuffer->Release();
1553                                 }
1554                                 if (vslog)
1555                                 {
1556                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1557                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1558                                         vslog->Release();
1559                                 }
1560                         }
1561                         if (fragstring && fragstring[0])
1562                         {
1563                                 if (debugshader)
1564                                 {
1565 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1566 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1567                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1568                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1569                                 }
1570                                 else
1571                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1572                                 if (psbuffer)
1573                                 {
1574                                         psbinsize = psbuffer->GetBufferSize();
1575                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1576                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1577                                         psbuffer->Release();
1578                                 }
1579                                 if (pslog)
1580                                 {
1581                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1582                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1583                                         pslog->Release();
1584                                 }
1585                         }
1586                         Sys_UnloadLibrary(&d3dx9_dll);
1587                 }
1588                 else
1589                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1590         }
1591         if (vsbin && psbin)
1592         {
1593                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1594                 if (FAILED(vsresult))
1595                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1596                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1597                 if (FAILED(psresult))
1598                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1599         }
1600         // free the shader data
1601         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1602         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1603 }
1604
1605 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1606 {
1607         int i;
1608         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1609         int vertstring_length = 0;
1610         int geomstring_length = 0;
1611         int fragstring_length = 0;
1612         char *t;
1613         char *vertexstring, *geometrystring, *fragmentstring;
1614         char *vertstring, *geomstring, *fragstring;
1615         char permutationname[256];
1616         char cachename[256];
1617         int vertstrings_count = 0;
1618         int geomstrings_count = 0;
1619         int fragstrings_count = 0;
1620         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1621         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1622         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1623
1624         if (p->compiled)
1625                 return;
1626         p->compiled = true;
1627         p->vertexshader = NULL;
1628         p->pixelshader = NULL;
1629
1630         permutationname[0] = 0;
1631         cachename[0] = 0;
1632         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1633         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1634         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1635
1636         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1637         strlcat(cachename, "hlsl/", sizeof(cachename));
1638
1639         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1640         vertstrings_count = 0;
1641         geomstrings_count = 0;
1642         fragstrings_count = 0;
1643         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1644         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1645         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1646
1647         // the first pretext is which type of shader to compile as
1648         // (later these will all be bound together as a program object)
1649         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1650         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1651         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1652
1653         // the second pretext is the mode (for example a light source)
1654         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1655         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1656         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1657         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1658         strlcat(cachename, modeinfo->name, sizeof(cachename));
1659
1660         // now add all the permutation pretexts
1661         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1662         {
1663                 if (permutation & (1<<i))
1664                 {
1665                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1666                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1667                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1668                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1669                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1670                 }
1671                 else
1672                 {
1673                         // keep line numbers correct
1674                         vertstrings_list[vertstrings_count++] = "\n";
1675                         geomstrings_list[geomstrings_count++] = "\n";
1676                         fragstrings_list[fragstrings_count++] = "\n";
1677                 }
1678         }
1679
1680         // add static parms
1681         R_CompileShader_AddStaticParms(mode, permutation);
1682         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683         vertstrings_count += shaderstaticparms_count;
1684         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1685         geomstrings_count += shaderstaticparms_count;
1686         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1687         fragstrings_count += shaderstaticparms_count;
1688
1689         // replace spaces in the cachename with _ characters
1690         for (i = 0;cachename[i];i++)
1691                 if (cachename[i] == ' ')
1692                         cachename[i] = '_';
1693
1694         // now append the shader text itself
1695         vertstrings_list[vertstrings_count++] = vertexstring;
1696         geomstrings_list[geomstrings_count++] = geometrystring;
1697         fragstrings_list[fragstrings_count++] = fragmentstring;
1698
1699         // if any sources were NULL, clear the respective list
1700         if (!vertexstring)
1701                 vertstrings_count = 0;
1702         if (!geometrystring)
1703                 geomstrings_count = 0;
1704         if (!fragmentstring)
1705                 fragstrings_count = 0;
1706
1707         vertstring_length = 0;
1708         for (i = 0;i < vertstrings_count;i++)
1709                 vertstring_length += strlen(vertstrings_list[i]);
1710         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1711         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1712                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1713
1714         geomstring_length = 0;
1715         for (i = 0;i < geomstrings_count;i++)
1716                 geomstring_length += strlen(geomstrings_list[i]);
1717         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1718         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1719                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1720
1721         fragstring_length = 0;
1722         for (i = 0;i < fragstrings_count;i++)
1723                 fragstring_length += strlen(fragstrings_list[i]);
1724         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1725         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1726                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1727
1728         // try to load the cached shader, or generate one
1729         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1730
1731         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1732                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1733         else
1734                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1735
1736         // free the strings
1737         if (vertstring)
1738                 Mem_Free(vertstring);
1739         if (geomstring)
1740                 Mem_Free(geomstring);
1741         if (fragstring)
1742                 Mem_Free(fragstring);
1743         if (vertexstring)
1744                 Mem_Free(vertexstring);
1745         if (geometrystring)
1746                 Mem_Free(geometrystring);
1747         if (fragmentstring)
1748                 Mem_Free(fragmentstring);
1749 }
1750
1751 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1752 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1753 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);}
1754 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);}
1755 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);}
1756 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);}
1757
1758 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1759 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1760 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);}
1761 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);}
1762 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);}
1763 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);}
1764
1765 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1766 {
1767         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1768         if (r_hlsl_permutation != perm)
1769         {
1770                 r_hlsl_permutation = perm;
1771                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1772                 {
1773                         if (!r_hlsl_permutation->compiled)
1774                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1775                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1776                         {
1777                                 // remove features until we find a valid permutation
1778                                 int i;
1779                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1780                                 {
1781                                         // reduce i more quickly whenever it would not remove any bits
1782                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1783                                         if (!(permutation & j))
1784                                                 continue;
1785                                         permutation -= j;
1786                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1787                                         if (!r_hlsl_permutation->compiled)
1788                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1789                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1790                                                 break;
1791                                 }
1792                                 if (i >= SHADERPERMUTATION_COUNT)
1793                                 {
1794                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1795                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1796                                         return; // no bit left to clear, entire mode is broken
1797                                 }
1798                         }
1799                 }
1800                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1801                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1802         }
1803         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1804         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1805         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1806 }
1807 #endif
1808
1809 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1810 {
1811         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1812         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1813         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1814         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1815 }
1816
1817 void R_GLSL_Restart_f(void)
1818 {
1819         unsigned int i, limit;
1820         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1821                 Mem_Free(glslshaderstring);
1822         glslshaderstring = NULL;
1823         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1824                 Mem_Free(hlslshaderstring);
1825         hlslshaderstring = NULL;
1826         switch(vid.renderpath)
1827         {
1828         case RENDERPATH_D3D9:
1829 #ifdef SUPPORTD3D
1830                 {
1831                         r_hlsl_permutation_t *p;
1832                         r_hlsl_permutation = NULL;
1833                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1834                         for (i = 0;i < limit;i++)
1835                         {
1836                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1837                                 {
1838                                         if (p->vertexshader)
1839                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1840                                         if (p->pixelshader)
1841                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1842                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1843                                 }
1844                         }
1845                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1846                 }
1847 #endif
1848                 break;
1849         case RENDERPATH_D3D10:
1850                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1851                 break;
1852         case RENDERPATH_D3D11:
1853                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1854                 break;
1855         case RENDERPATH_GL20:
1856         case RENDERPATH_GLES2:
1857                 {
1858                         r_glsl_permutation_t *p;
1859                         r_glsl_permutation = NULL;
1860                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1861                         for (i = 0;i < limit;i++)
1862                         {
1863                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1864                                 {
1865                                         GL_Backend_FreeProgram(p->program);
1866                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1867                                 }
1868                         }
1869                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1870                 }
1871                 break;
1872         case RENDERPATH_GL11:
1873         case RENDERPATH_GL13:
1874         case RENDERPATH_GLES1:
1875                 break;
1876         case RENDERPATH_SOFT:
1877                 break;
1878         }
1879 }
1880
1881 void R_GLSL_DumpShader_f(void)
1882 {
1883         int i;
1884         qfile_t *file;
1885
1886         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1887         if (file)
1888         {
1889                 FS_Print(file, "/* The engine may define the following macros:\n");
1890                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1891                 for (i = 0;i < SHADERMODE_COUNT;i++)
1892                         FS_Print(file, glslshadermodeinfo[i].pretext);
1893                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1894                         FS_Print(file, shaderpermutationinfo[i].pretext);
1895                 FS_Print(file, "*/\n");
1896                 FS_Print(file, builtinshaderstring);
1897                 FS_Close(file);
1898                 Con_Printf("glsl/default.glsl written\n");
1899         }
1900         else
1901                 Con_Printf("failed to write to glsl/default.glsl\n");
1902
1903         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1904         if (file)
1905         {
1906                 FS_Print(file, "/* The engine may define the following macros:\n");
1907                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1908                 for (i = 0;i < SHADERMODE_COUNT;i++)
1909                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1910                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1911                         FS_Print(file, shaderpermutationinfo[i].pretext);
1912                 FS_Print(file, "*/\n");
1913                 FS_Print(file, builtinhlslshaderstring);
1914                 FS_Close(file);
1915                 Con_Printf("hlsl/default.hlsl written\n");
1916         }
1917         else
1918                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1919 }
1920
1921 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1922 {
1923         unsigned int permutation = 0;
1924         if (r_trippy.integer && !notrippy)
1925                 permutation |= SHADERPERMUTATION_TRIPPY;
1926         permutation |= SHADERPERMUTATION_VIEWTINT;
1927         if (first)
1928                 permutation |= SHADERPERMUTATION_DIFFUSE;
1929         if (second)
1930                 permutation |= SHADERPERMUTATION_SPECULAR;
1931         if (texturemode == GL_MODULATE)
1932                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1933         else if (texturemode == GL_ADD)
1934                 permutation |= SHADERPERMUTATION_GLOW;
1935         else if (texturemode == GL_DECAL)
1936                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1937         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1938                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1939         if (!second)
1940                 texturemode = GL_MODULATE;
1941         if (vid.allowalphatocoverage)
1942                 GL_AlphaToCoverage(false);
1943         switch (vid.renderpath)
1944         {
1945         case RENDERPATH_D3D9:
1946 #ifdef SUPPORTD3D
1947                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1948                 R_Mesh_TexBind(GL20TU_FIRST , first );
1949                 R_Mesh_TexBind(GL20TU_SECOND, second);
1950                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1951                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1952 #endif
1953                 break;
1954         case RENDERPATH_D3D10:
1955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956                 break;
1957         case RENDERPATH_D3D11:
1958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959                 break;
1960         case RENDERPATH_GL20:
1961         case RENDERPATH_GLES2:
1962                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1963                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1964                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1965                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1966                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1967                 break;
1968         case RENDERPATH_GL13:
1969         case RENDERPATH_GLES1:
1970                 R_Mesh_TexBind(0, first );
1971                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1972                 R_Mesh_TexBind(1, second);
1973                 if (second)
1974                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1975                 break;
1976         case RENDERPATH_GL11:
1977                 R_Mesh_TexBind(0, first );
1978                 break;
1979         case RENDERPATH_SOFT:
1980                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1981                 R_Mesh_TexBind(GL20TU_FIRST , first );
1982                 R_Mesh_TexBind(GL20TU_SECOND, second);
1983                 break;
1984         }
1985 }
1986
1987 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1988 {
1989         unsigned int permutation = 0;
1990         if (r_trippy.integer && !notrippy)
1991                 permutation |= SHADERPERMUTATION_TRIPPY;
1992         if (vid.allowalphatocoverage)
1993                 GL_AlphaToCoverage(false);
1994         switch (vid.renderpath)
1995         {
1996         case RENDERPATH_D3D9:
1997 #ifdef SUPPORTD3D
1998                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1999 #endif
2000                 break;
2001         case RENDERPATH_D3D10:
2002                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2003                 break;
2004         case RENDERPATH_D3D11:
2005                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2006                 break;
2007         case RENDERPATH_GL20:
2008         case RENDERPATH_GLES2:
2009                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2010                 break;
2011         case RENDERPATH_GL13:
2012         case RENDERPATH_GLES1:
2013                 R_Mesh_TexBind(0, 0);
2014                 R_Mesh_TexBind(1, 0);
2015                 break;
2016         case RENDERPATH_GL11:
2017                 R_Mesh_TexBind(0, 0);
2018                 break;
2019         case RENDERPATH_SOFT:
2020                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2021                 break;
2022         }
2023 }
2024
2025 void R_SetupShader_ShowDepth(qboolean notrippy)
2026 {
2027         int permutation = 0;
2028         if (r_trippy.integer && !notrippy)
2029                 permutation |= SHADERPERMUTATION_TRIPPY;
2030         if (vid.allowalphatocoverage)
2031                 GL_AlphaToCoverage(false);
2032         switch (vid.renderpath)
2033         {
2034         case RENDERPATH_D3D9:
2035 #ifdef SUPPORTHLSL
2036                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2037 #endif
2038                 break;
2039         case RENDERPATH_D3D10:
2040                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2041                 break;
2042         case RENDERPATH_D3D11:
2043                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2044                 break;
2045         case RENDERPATH_GL20:
2046         case RENDERPATH_GLES2:
2047                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2048                 break;
2049         case RENDERPATH_GL13:
2050         case RENDERPATH_GLES1:
2051                 break;
2052         case RENDERPATH_GL11:
2053                 break;
2054         case RENDERPATH_SOFT:
2055                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2056                 break;
2057         }
2058 }
2059
2060 extern qboolean r_shadow_usingdeferredprepass;
2061 extern cvar_t r_shadow_deferred_8bitrange;
2062 extern rtexture_t *r_shadow_attenuationgradienttexture;
2063 extern rtexture_t *r_shadow_attenuation2dtexture;
2064 extern rtexture_t *r_shadow_attenuation3dtexture;
2065 extern qboolean r_shadow_usingshadowmap2d;
2066 extern qboolean r_shadow_usingshadowmaportho;
2067 extern float r_shadow_shadowmap_texturescale[2];
2068 extern float r_shadow_shadowmap_parameters[4];
2069 extern qboolean r_shadow_shadowmapvsdct;
2070 extern qboolean r_shadow_shadowmapsampler;
2071 extern int r_shadow_shadowmappcf;
2072 extern rtexture_t *r_shadow_shadowmap2dtexture;
2073 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2074 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2075 extern matrix4x4_t r_shadow_shadowmapmatrix;
2076 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2077 extern int r_shadow_prepass_width;
2078 extern int r_shadow_prepass_height;
2079 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2080 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2081 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2082 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2083 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2084
2085 #define BLENDFUNC_ALLOWS_COLORMOD      1
2086 #define BLENDFUNC_ALLOWS_FOG           2
2087 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2088 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2089 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2090 static int R_BlendFuncFlags(int src, int dst)
2091 {
2092         int r = 0;
2093
2094         // a blendfunc allows colormod if:
2095         // a) it can never keep the destination pixel invariant, or
2096         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2097         // this is to prevent unintended side effects from colormod
2098
2099         // a blendfunc allows fog if:
2100         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2101         // this is to prevent unintended side effects from fog
2102
2103         // these checks are the output of fogeval.pl
2104
2105         r |= BLENDFUNC_ALLOWS_COLORMOD;
2106         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2107         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2108         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2111         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2114         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2115         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2116         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2118         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2122         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2123         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2124         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2125         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2126         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2127
2128         return r;
2129 }
2130
2131 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)
2132 {
2133         // select a permutation of the lighting shader appropriate to this
2134         // combination of texture, entity, light source, and fogging, only use the
2135         // minimum features necessary to avoid wasting rendering time in the
2136         // fragment shader on features that are not being used
2137         unsigned int permutation = 0;
2138         unsigned int mode = 0;
2139         int blendfuncflags;
2140         static float dummy_colormod[3] = {1, 1, 1};
2141         float *colormod = rsurface.colormod;
2142         float m16f[16];
2143         matrix4x4_t tempmatrix;
2144         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2145         if (r_trippy.integer && !notrippy)
2146                 permutation |= SHADERPERMUTATION_TRIPPY;
2147         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2148                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2149         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2150                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2151         if (rsurfacepass == RSURFPASS_BACKGROUND)
2152         {
2153                 // distorted background
2154                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2155                 {
2156                         mode = SHADERMODE_WATER;
2157                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2158                         {
2159                                 // this is the right thing to do for wateralpha
2160                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2161                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2162                         }
2163                         else
2164                         {
2165                                 // this is the right thing to do for entity alpha
2166                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2167                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2168                         }
2169                 }
2170                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2171                 {
2172                         mode = SHADERMODE_REFRACTION;
2173                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2174                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2175                 }
2176                 else
2177                 {
2178                         mode = SHADERMODE_GENERIC;
2179                         permutation |= SHADERPERMUTATION_DIFFUSE;
2180                         GL_BlendFunc(GL_ONE, GL_ZERO);
2181                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2182                 }
2183                 if (vid.allowalphatocoverage)
2184                         GL_AlphaToCoverage(false);
2185         }
2186         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2187         {
2188                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2189                 {
2190                         switch(rsurface.texture->offsetmapping)
2191                         {
2192                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2193                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2194                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_OFF: break;
2196                         }
2197                 }
2198                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2199                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2200                 // normalmap (deferred prepass), may use alpha test on diffuse
2201                 mode = SHADERMODE_DEFERREDGEOMETRY;
2202                 GL_BlendFunc(GL_ONE, GL_ZERO);
2203                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2204                 if (vid.allowalphatocoverage)
2205                         GL_AlphaToCoverage(false);
2206         }
2207         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2208         {
2209                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2210                 {
2211                         switch(rsurface.texture->offsetmapping)
2212                         {
2213                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2214                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2215                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2216                         case OFFSETMAPPING_OFF: break;
2217                         }
2218                 }
2219                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2220                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2221                 // light source
2222                 mode = SHADERMODE_LIGHTSOURCE;
2223                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2224                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2225                 if (diffusescale > 0)
2226                         permutation |= SHADERPERMUTATION_DIFFUSE;
2227                 if (specularscale > 0)
2228                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2229                 if (r_refdef.fogenabled)
2230                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2231                 if (rsurface.texture->colormapping)
2232                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2233                 if (r_shadow_usingshadowmap2d)
2234                 {
2235                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2236                         if(r_shadow_shadowmapvsdct)
2237                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2238
2239                         if (r_shadow_shadowmapsampler)
2240                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2241                         if (r_shadow_shadowmappcf > 1)
2242                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2243                         else if (r_shadow_shadowmappcf)
2244                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2245                 }
2246                 if (rsurface.texture->reflectmasktexture)
2247                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2248                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2249                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2250                 if (vid.allowalphatocoverage)
2251                         GL_AlphaToCoverage(false);
2252         }
2253         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2254         {
2255                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2256                 {
2257                         switch(rsurface.texture->offsetmapping)
2258                         {
2259                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2260                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2261                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2262                         case OFFSETMAPPING_OFF: break;
2263                         }
2264                 }
2265                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2266                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2267                 // unshaded geometry (fullbright or ambient model lighting)
2268                 mode = SHADERMODE_FLATCOLOR;
2269                 ambientscale = diffusescale = specularscale = 0;
2270                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2271                         permutation |= SHADERPERMUTATION_GLOW;
2272                 if (r_refdef.fogenabled)
2273                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2274                 if (rsurface.texture->colormapping)
2275                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2276                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2277                 {
2278                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2279                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2280
2281                         if (r_shadow_shadowmapsampler)
2282                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2283                         if (r_shadow_shadowmappcf > 1)
2284                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2285                         else if (r_shadow_shadowmappcf)
2286                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2287                 }
2288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2289                         permutation |= SHADERPERMUTATION_REFLECTION;
2290                 if (rsurface.texture->reflectmasktexture)
2291                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2292                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2294                 // when using alphatocoverage, we don't need alphakill
2295                 if (vid.allowalphatocoverage)
2296                 {
2297                         if (r_transparent_alphatocoverage.integer)
2298                         {
2299                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2300                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2301                         }
2302                         else
2303                                 GL_AlphaToCoverage(false);
2304                 }
2305         }
2306         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2307         {
2308                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2309                 {
2310                         switch(rsurface.texture->offsetmapping)
2311                         {
2312                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2313                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2314                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315                         case OFFSETMAPPING_OFF: break;
2316                         }
2317                 }
2318                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2319                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2320                 // directional model lighting
2321                 mode = SHADERMODE_LIGHTDIRECTION;
2322                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2323                         permutation |= SHADERPERMUTATION_GLOW;
2324                 permutation |= SHADERPERMUTATION_DIFFUSE;
2325                 if (specularscale > 0)
2326                         permutation |= SHADERPERMUTATION_SPECULAR;
2327                 if (r_refdef.fogenabled)
2328                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2329                 if (rsurface.texture->colormapping)
2330                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2331                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2332                 {
2333                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2334                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2335
2336                         if (r_shadow_shadowmapsampler)
2337                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2338                         if (r_shadow_shadowmappcf > 1)
2339                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2340                         else if (r_shadow_shadowmappcf)
2341                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2342                 }
2343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2344                         permutation |= SHADERPERMUTATION_REFLECTION;
2345                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2346                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2347                 if (rsurface.texture->reflectmasktexture)
2348                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2349                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2350                 {
2351                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2352                         if (r_shadow_bouncegriddirectional)
2353                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2354                 }
2355                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2356                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357                 // when using alphatocoverage, we don't need alphakill
2358                 if (vid.allowalphatocoverage)
2359                 {
2360                         if (r_transparent_alphatocoverage.integer)
2361                         {
2362                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2363                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2364                         }
2365                         else
2366                                 GL_AlphaToCoverage(false);
2367                 }
2368         }
2369         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2370         {
2371                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2372                 {
2373                         switch(rsurface.texture->offsetmapping)
2374                         {
2375                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2376                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2377                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378                         case OFFSETMAPPING_OFF: break;
2379                         }
2380                 }
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2382                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2383                 // ambient model lighting
2384                 mode = SHADERMODE_LIGHTDIRECTION;
2385                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2386                         permutation |= SHADERPERMUTATION_GLOW;
2387                 if (r_refdef.fogenabled)
2388                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2389                 if (rsurface.texture->colormapping)
2390                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2391                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2392                 {
2393                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2394                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2395
2396                         if (r_shadow_shadowmapsampler)
2397                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2398                         if (r_shadow_shadowmappcf > 1)
2399                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2400                         else if (r_shadow_shadowmappcf)
2401                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2402                 }
2403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2404                         permutation |= SHADERPERMUTATION_REFLECTION;
2405                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2406                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2407                 if (rsurface.texture->reflectmasktexture)
2408                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2409                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2410                 {
2411                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2412                         if (r_shadow_bouncegriddirectional)
2413                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2414                 }
2415                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2416                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2417                 // when using alphatocoverage, we don't need alphakill
2418                 if (vid.allowalphatocoverage)
2419                 {
2420                         if (r_transparent_alphatocoverage.integer)
2421                         {
2422                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2423                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2424                         }
2425                         else
2426                                 GL_AlphaToCoverage(false);
2427                 }
2428         }
2429         else
2430         {
2431                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2432                 {
2433                         switch(rsurface.texture->offsetmapping)
2434                         {
2435                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2436                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2437                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2438                         case OFFSETMAPPING_OFF: break;
2439                         }
2440                 }
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2442                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2443                 // lightmapped wall
2444                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2445                         permutation |= SHADERPERMUTATION_GLOW;
2446                 if (r_refdef.fogenabled)
2447                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2448                 if (rsurface.texture->colormapping)
2449                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2450                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2451                 {
2452                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2453                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2454
2455                         if (r_shadow_shadowmapsampler)
2456                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2457                         if (r_shadow_shadowmappcf > 1)
2458                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2459                         else if (r_shadow_shadowmappcf)
2460                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2461                 }
2462                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2463                         permutation |= SHADERPERMUTATION_REFLECTION;
2464                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2465                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2466                 if (rsurface.texture->reflectmasktexture)
2467                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2468                 if (FAKELIGHT_ENABLED)
2469                 {
2470                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2471                         mode = SHADERMODE_FAKELIGHT;
2472                         permutation |= SHADERPERMUTATION_DIFFUSE;
2473                         if (specularscale > 0)
2474                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2475                 }
2476                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2477                 {
2478                         // deluxemapping (light direction texture)
2479                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2480                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2481                         else
2482                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2483                         permutation |= SHADERPERMUTATION_DIFFUSE;
2484                         if (specularscale > 0)
2485                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2486                 }
2487                 else if (r_glsl_deluxemapping.integer >= 2)
2488                 {
2489                         // fake deluxemapping (uniform light direction in tangentspace)
2490                         if (rsurface.uselightmaptexture)
2491                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2492                         else
2493                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2494                         permutation |= SHADERPERMUTATION_DIFFUSE;
2495                         if (specularscale > 0)
2496                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2497                 }
2498                 else if (rsurface.uselightmaptexture)
2499                 {
2500                         // ordinary lightmapping (q1bsp, q3bsp)
2501                         mode = SHADERMODE_LIGHTMAP;
2502                 }
2503                 else
2504                 {
2505                         // ordinary vertex coloring (q3bsp)
2506                         mode = SHADERMODE_VERTEXCOLOR;
2507                 }
2508                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2509                 {
2510                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2511                         if (r_shadow_bouncegriddirectional)
2512                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2513                 }
2514                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2515                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2516                 // when using alphatocoverage, we don't need alphakill
2517                 if (vid.allowalphatocoverage)
2518                 {
2519                         if (r_transparent_alphatocoverage.integer)
2520                         {
2521                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2522                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2523                         }
2524                         else
2525                                 GL_AlphaToCoverage(false);
2526                 }
2527         }
2528         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2529                 colormod = dummy_colormod;
2530         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2531                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2532         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2533                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2534         switch(vid.renderpath)
2535         {
2536         case RENDERPATH_D3D9:
2537 #ifdef SUPPORTD3D
2538                 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);
2539                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2540                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2541                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2542                 if (mode == SHADERMODE_LIGHTSOURCE)
2543                 {
2544                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2545                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2546                 }
2547                 else
2548                 {
2549                         if (mode == SHADERMODE_LIGHTDIRECTION)
2550                         {
2551                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2552                         }
2553                 }
2554                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2555                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2556                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2557                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2558                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2559
2560                 if (mode == SHADERMODE_LIGHTSOURCE)
2561                 {
2562                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2563                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2564                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2565                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2566                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2567
2568                         // additive passes are only darkened by fog, not tinted
2569                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2570                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2571                 }
2572                 else
2573                 {
2574                         if (mode == SHADERMODE_FLATCOLOR)
2575                         {
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2577                         }
2578                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2579                         {
2580                                 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]);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2582                                 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);
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2587                         }
2588                         else
2589                         {
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2591                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2592                                 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);
2593                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2595                         }
2596                         // additive passes are only darkened by fog, not tinted
2597                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2599                         else
2600                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2601                         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);
2602                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2603                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2604                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2605                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2606                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2607                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2608                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2609                         if (mode == SHADERMODE_WATER)
2610                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2611                 }
2612                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2613                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2614                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2615                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2616                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2617                 if (rsurface.texture->pantstexture)
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2619                 else
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2621                 if (rsurface.texture->shirttexture)
2622                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2623                 else
2624                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2625                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2626                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2627                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2628                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2629                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2630                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2631                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2632                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2633                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2634                         );
2635                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2636                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2637                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2638                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2639
2640                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2641                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2642                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2643                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2645                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2646                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2647                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2648                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2649                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2650                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2651                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2652                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2653                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2654                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2655                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2656                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2657                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2658                 {
2659                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2660                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2661                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2662                 }
2663                 else
2664                 {
2665                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2666                 }
2667 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2668 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2669                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2670                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2671                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2672                 {
2673                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2674                         if (rsurface.rtlight)
2675                         {
2676                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2677                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2678                         }
2679                 }
2680 #endif
2681                 break;
2682         case RENDERPATH_D3D10:
2683                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2684                 break;
2685         case RENDERPATH_D3D11:
2686                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2687                 break;
2688         case RENDERPATH_GL20:
2689         case RENDERPATH_GLES2:
2690                 if (!vid.useinterleavedarrays)
2691                 {
2692                         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);
2693                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2694                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2695                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2696                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2697                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2698                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2699                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2700                 }
2701                 else
2702                 {
2703                         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);
2704                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2705                 }
2706                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2707                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2708                 if (mode == SHADERMODE_LIGHTSOURCE)
2709                 {
2710                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2711                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2712                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2713                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2714                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2715                         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);
2716         
2717                         // additive passes are only darkened by fog, not tinted
2718                         if (r_glsl_permutation->loc_FogColor >= 0)
2719                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2720                         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);
2721                 }
2722                 else
2723                 {
2724                         if (mode == SHADERMODE_FLATCOLOR)
2725                         {
2726                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2727                         }
2728                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2729                         {
2730                                 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]);
2731                                 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]);
2732                                 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);
2733                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2734                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2735                                 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]);
2736                                 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]);
2737                         }
2738                         else
2739                         {
2740                                 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]);
2741                                 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]);
2742                                 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);
2743                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2744                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2745                         }
2746                         // additive passes are only darkened by fog, not tinted
2747                         if (r_glsl_permutation->loc_FogColor >= 0)
2748                         {
2749                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2750                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2751                                 else
2752                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2753                         }
2754                         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);
2755                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2756                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2757                         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]);
2758                         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]);
2759                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2760                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2761                         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);
2762                         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]);
2763                 }
2764                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2765                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2766                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2767                 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]);
2768                 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]);
2769
2770                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2771                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2772                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2773                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2774                 {
2775                         if (rsurface.texture->pantstexture)
2776                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2777                         else
2778                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2779                 }
2780                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2781                 {
2782                         if (rsurface.texture->shirttexture)
2783                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2784                         else
2785                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2786                 }
2787                 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]);
2788                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2789                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2790                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2791                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2792                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2793                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2794                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2795                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2796                         );
2797                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2798                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2799                 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]);
2800                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2801                 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);}
2802                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2803
2804                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2805                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2806                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2807                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2808                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2809                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2810                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2811                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2812                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2813                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2814                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2815                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2816                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2817                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2818                 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);
2819                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2820                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2821                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2822                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2823                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2824                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2825                 {
2826                         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);
2827                         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);
2828                         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);
2829                 }
2830                 else
2831                 {
2832                         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);
2833                 }
2834                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2835                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2836                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2837                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2838                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2839                 {
2840                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2841                         if (rsurface.rtlight)
2842                         {
2843                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2844                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2845                         }
2846                 }
2847                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2848                 CHECKGLERROR
2849                 break;
2850         case RENDERPATH_GL11:
2851         case RENDERPATH_GL13:
2852         case RENDERPATH_GLES1:
2853                 break;
2854         case RENDERPATH_SOFT:
2855                 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);
2856                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2857                 R_SetupShader_SetPermutationSoft(mode, permutation);
2858                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2859                 if (mode == SHADERMODE_LIGHTSOURCE)
2860                 {
2861                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2862                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2864                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2865                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2866                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2867         
2868                         // additive passes are only darkened by fog, not tinted
2869                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2870                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2871                 }
2872                 else
2873                 {
2874                         if (mode == SHADERMODE_FLATCOLOR)
2875                         {
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2877                         }
2878                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2879                         {
2880                                 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]);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2882                                 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);
2883                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2885                                 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]);
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2887                         }
2888                         else
2889                         {
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2891                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2892                                 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);
2893                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2895                         }
2896                         // additive passes are only darkened by fog, not tinted
2897                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2898                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2899                         else
2900                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2901                         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);
2902                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2903                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2904                         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]);
2905                         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]);
2906                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2907                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2908                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2909                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2910                 }
2911                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2912                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2913                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2914                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2915                 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]);
2916
2917                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2918                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2919                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2920                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2921                 {
2922                         if (rsurface.texture->pantstexture)
2923                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2924                         else
2925                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2926                 }
2927                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2928                 {
2929                         if (rsurface.texture->shirttexture)
2930                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2931                         else
2932                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2933                 }
2934                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2935                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2936                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2937                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2938                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2939                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2940                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2941                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2942                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2943                         );
2944                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2945                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2946                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2947                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2948
2949                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2950                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2951                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2952                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2953                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2954                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2955                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2956                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2957                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2958                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2959                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2960                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2961                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2962                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2963                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2964                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2965                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2966                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2967                 {
2968                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2969                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2970                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2971                 }
2972                 else
2973                 {
2974                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2975                 }
2976 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2977 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2978                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2979                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2980                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2981                 {
2982                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2983                         if (rsurface.rtlight)
2984                         {
2985                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2986                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2987                         }
2988                 }
2989                 break;
2990         }
2991 }
2992
2993 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2994 {
2995         // select a permutation of the lighting shader appropriate to this
2996         // combination of texture, entity, light source, and fogging, only use the
2997         // minimum features necessary to avoid wasting rendering time in the
2998         // fragment shader on features that are not being used
2999         unsigned int permutation = 0;
3000         unsigned int mode = 0;
3001         const float *lightcolorbase = rtlight->currentcolor;
3002         float ambientscale = rtlight->ambientscale;
3003         float diffusescale = rtlight->diffusescale;
3004         float specularscale = rtlight->specularscale;
3005         // this is the location of the light in view space
3006         vec3_t viewlightorigin;
3007         // this transforms from view space (camera) to light space (cubemap)
3008         matrix4x4_t viewtolight;
3009         matrix4x4_t lighttoview;
3010         float viewtolight16f[16];
3011         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3012         // light source
3013         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3014         if (rtlight->currentcubemap != r_texture_whitecube)
3015                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3016         if (diffusescale > 0)
3017                 permutation |= SHADERPERMUTATION_DIFFUSE;
3018         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3019                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3020         if (r_shadow_usingshadowmap2d)
3021         {
3022                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3023                 if (r_shadow_shadowmapvsdct)
3024                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3025
3026                 if (r_shadow_shadowmapsampler)
3027                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3028                 if (r_shadow_shadowmappcf > 1)
3029                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3030                 else if (r_shadow_shadowmappcf)
3031                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3032         }
3033         if (vid.allowalphatocoverage)
3034                 GL_AlphaToCoverage(false);
3035         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3036         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3037         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3038         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3039         switch(vid.renderpath)
3040         {
3041         case RENDERPATH_D3D9:
3042 #ifdef SUPPORTD3D
3043                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3044                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3045                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3046                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3047                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3048                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3049                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3050                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3051                 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);
3052                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3053                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3054
3055                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3056                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3057                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3058                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3059                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3060                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3061 #endif
3062                 break;
3063         case RENDERPATH_D3D10:
3064                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3065                 break;
3066         case RENDERPATH_D3D11:
3067                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3068                 break;
3069         case RENDERPATH_GL20:
3070         case RENDERPATH_GLES2:
3071                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3072                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3073                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3074                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3075                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3076                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3077                 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]);
3078                 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]);
3079                 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);
3080                 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]);
3081                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3082
3083                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3084                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3085                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3086                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3087                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3088                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3089                 break;
3090         case RENDERPATH_GL11:
3091         case RENDERPATH_GL13:
3092         case RENDERPATH_GLES1:
3093                 break;
3094         case RENDERPATH_SOFT:
3095                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3096                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3097                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3098                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3099                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3100                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3101                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3102                 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]);
3103                 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);
3104                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3105                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3106
3107                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3108                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3109                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3110                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3111                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3112                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3113                 break;
3114         }
3115 }
3116
3117 #define SKINFRAME_HASH 1024
3118
3119 typedef struct
3120 {
3121         int loadsequence; // incremented each level change
3122         memexpandablearray_t array;
3123         skinframe_t *hash[SKINFRAME_HASH];
3124 }
3125 r_skinframe_t;
3126 r_skinframe_t r_skinframe;
3127
3128 void R_SkinFrame_PrepareForPurge(void)
3129 {
3130         r_skinframe.loadsequence++;
3131         // wrap it without hitting zero
3132         if (r_skinframe.loadsequence >= 200)
3133                 r_skinframe.loadsequence = 1;
3134 }
3135
3136 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3137 {
3138         if (!skinframe)
3139                 return;
3140         // mark the skinframe as used for the purging code
3141         skinframe->loadsequence = r_skinframe.loadsequence;
3142 }
3143
3144 void R_SkinFrame_Purge(void)
3145 {
3146         int i;
3147         skinframe_t *s;
3148         for (i = 0;i < SKINFRAME_HASH;i++)
3149         {
3150                 for (s = r_skinframe.hash[i];s;s = s->next)
3151                 {
3152                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3153                         {
3154                                 if (s->merged == s->base)
3155                                         s->merged = NULL;
3156                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3157                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3158                                 R_PurgeTexture(s->merged);s->merged = NULL;
3159                                 R_PurgeTexture(s->base  );s->base   = NULL;
3160                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3161                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3162                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3163                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3164                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3165                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3166                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3167                                 s->loadsequence = 0;
3168                         }
3169                 }
3170         }
3171 }
3172
3173 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3174         skinframe_t *item;
3175         char basename[MAX_QPATH];
3176
3177         Image_StripImageExtension(name, basename, sizeof(basename));
3178
3179         if( last == NULL ) {
3180                 int hashindex;
3181                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3182                 item = r_skinframe.hash[hashindex];
3183         } else {
3184                 item = last->next;
3185         }
3186
3187         // linearly search through the hash bucket
3188         for( ; item ; item = item->next ) {
3189                 if( !strcmp( item->basename, basename ) ) {
3190                         return item;
3191                 }
3192         }
3193         return NULL;
3194 }
3195
3196 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3197 {
3198         skinframe_t *item;
3199         int hashindex;
3200         char basename[MAX_QPATH];
3201
3202         Image_StripImageExtension(name, basename, sizeof(basename));
3203
3204         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3205         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3206                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3207                         break;
3208
3209         if (!item) {
3210                 rtexture_t *dyntexture;
3211                 // check whether its a dynamic texture
3212                 dyntexture = CL_GetDynTexture( basename );
3213                 if (!add && !dyntexture)
3214                         return NULL;
3215                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3216                 memset(item, 0, sizeof(*item));
3217                 strlcpy(item->basename, basename, sizeof(item->basename));
3218                 item->base = dyntexture; // either NULL or dyntexture handle
3219                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3220                 item->comparewidth = comparewidth;
3221                 item->compareheight = compareheight;
3222                 item->comparecrc = comparecrc;
3223                 item->next = r_skinframe.hash[hashindex];
3224                 r_skinframe.hash[hashindex] = item;
3225         }
3226         else if (textureflags & TEXF_FORCE_RELOAD)
3227         {
3228                 rtexture_t *dyntexture;
3229                 // check whether its a dynamic texture
3230                 dyntexture = CL_GetDynTexture( basename );
3231                 if (!add && !dyntexture)
3232                         return NULL;
3233                 if (item->merged == item->base)
3234                         item->merged = NULL;
3235                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3236                 R_PurgeTexture(item->stain );item->stain  = NULL;
3237                 R_PurgeTexture(item->merged);item->merged = NULL;
3238                 R_PurgeTexture(item->base  );item->base   = NULL;
3239                 R_PurgeTexture(item->pants );item->pants  = NULL;
3240                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3241                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3242                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3243                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3244                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3245         R_PurgeTexture(item->reflect);item->reflect = NULL;
3246                 item->loadsequence = 0;
3247         }
3248         else if( item->base == NULL )
3249         {
3250                 rtexture_t *dyntexture;
3251                 // check whether its a dynamic texture
3252                 // 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]
3253                 dyntexture = CL_GetDynTexture( basename );
3254                 item->base = dyntexture; // either NULL or dyntexture handle
3255         }
3256
3257         R_SkinFrame_MarkUsed(item);
3258         return item;
3259 }
3260
3261 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3262         { \
3263                 unsigned long long avgcolor[5], wsum; \
3264                 int pix, comp, w; \
3265                 avgcolor[0] = 0; \
3266                 avgcolor[1] = 0; \
3267                 avgcolor[2] = 0; \
3268                 avgcolor[3] = 0; \
3269                 avgcolor[4] = 0; \
3270                 wsum = 0; \
3271                 for(pix = 0; pix < cnt; ++pix) \
3272                 { \
3273                         w = 0; \
3274                         for(comp = 0; comp < 3; ++comp) \
3275                                 w += getpixel; \
3276                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3277                         { \
3278                                 ++wsum; \
3279                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3280                                 w = getpixel; \
3281                                 for(comp = 0; comp < 3; ++comp) \
3282                                         avgcolor[comp] += getpixel * w; \
3283                                 avgcolor[3] += w; \
3284                         } \
3285                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3286                         avgcolor[4] += getpixel; \
3287                 } \
3288                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3289                         avgcolor[3] = 1; \
3290                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3291                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3292                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3293                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3294         }
3295
3296 extern cvar_t gl_picmip;
3297 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3298 {
3299         int j;
3300         unsigned char *pixels;
3301         unsigned char *bumppixels;
3302         unsigned char *basepixels = NULL;
3303         int basepixels_width = 0;
3304         int basepixels_height = 0;
3305         skinframe_t *skinframe;
3306         rtexture_t *ddsbase = NULL;
3307         qboolean ddshasalpha = false;
3308         float ddsavgcolor[4];
3309         char basename[MAX_QPATH];
3310         int miplevel = R_PicmipForFlags(textureflags);
3311         int savemiplevel = miplevel;
3312         int mymiplevel;
3313
3314         if (cls.state == ca_dedicated)
3315                 return NULL;
3316
3317         // return an existing skinframe if already loaded
3318         // if loading of the first image fails, don't make a new skinframe as it
3319         // would cause all future lookups of this to be missing
3320         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3321         if (skinframe && skinframe->base)
3322                 return skinframe;
3323
3324         Image_StripImageExtension(name, basename, sizeof(basename));
3325
3326         // check for DDS texture file first
3327         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3328         {
3329                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3330                 if (basepixels == NULL)
3331                         return NULL;
3332         }
3333
3334         // FIXME handle miplevel
3335
3336         if (developer_loading.integer)
3337                 Con_Printf("loading skin \"%s\"\n", name);
3338
3339         // we've got some pixels to store, so really allocate this new texture now
3340         if (!skinframe)
3341                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3342         textureflags &= ~TEXF_FORCE_RELOAD;
3343         skinframe->stain = NULL;
3344         skinframe->merged = NULL;
3345         skinframe->base = NULL;
3346         skinframe->pants = NULL;
3347         skinframe->shirt = NULL;
3348         skinframe->nmap = NULL;
3349         skinframe->gloss = NULL;
3350         skinframe->glow = NULL;
3351         skinframe->fog = NULL;
3352         skinframe->reflect = NULL;
3353         skinframe->hasalpha = false;
3354
3355         if (ddsbase)
3356         {
3357                 skinframe->base = ddsbase;
3358                 skinframe->hasalpha = ddshasalpha;
3359                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3360                 if (r_loadfog && skinframe->hasalpha)
3361                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3362                 //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]);
3363         }
3364         else
3365         {
3366                 basepixels_width = image_width;
3367                 basepixels_height = image_height;
3368                 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);
3369                 if (textureflags & TEXF_ALPHA)
3370                 {
3371                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3372                         {
3373                                 if (basepixels[j] < 255)
3374                                 {
3375                                         skinframe->hasalpha = true;
3376                                         break;
3377                                 }
3378                         }
3379                         if (r_loadfog && skinframe->hasalpha)
3380                         {
3381                                 // has transparent pixels
3382                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3383                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3384                                 {
3385                                         pixels[j+0] = 255;
3386                                         pixels[j+1] = 255;
3387                                         pixels[j+2] = 255;
3388                                         pixels[j+3] = basepixels[j+3];
3389                                 }
3390                                 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);
3391                                 Mem_Free(pixels);
3392                         }
3393                 }
3394                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3395 #ifndef USE_GLES2
3396                 //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]);
3397                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3398                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3399                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3400                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3401 #endif
3402         }
3403
3404         if (r_loaddds)
3405         {
3406                 mymiplevel = savemiplevel;
3407                 if (r_loadnormalmap)
3408                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3409                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3410                 if (r_loadgloss)
3411                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3412                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3413                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3414                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3415         }
3416
3417         // _norm is the name used by tenebrae and has been adopted as standard
3418         if (r_loadnormalmap && skinframe->nmap == NULL)
3419         {
3420                 mymiplevel = savemiplevel;
3421                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3422                 {
3423                         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);
3424                         Mem_Free(pixels);
3425                         pixels = NULL;
3426                 }
3427                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3428                 {
3429                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3430                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3431                         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);
3432                         Mem_Free(pixels);
3433                         Mem_Free(bumppixels);
3434                 }
3435                 else if (r_shadow_bumpscale_basetexture.value > 0)
3436                 {
3437                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3438                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3439                         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);
3440                         Mem_Free(pixels);
3441                 }
3442 #ifndef USE_GLES2
3443                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3444                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3445 #endif
3446         }
3447
3448         // _luma is supported only for tenebrae compatibility
3449         // _glow is the preferred name
3450         mymiplevel = savemiplevel;
3451         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))))
3452         {
3453                 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);
3454 #ifndef USE_GLES2
3455                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3456                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3457 #endif
3458                 Mem_Free(pixels);pixels = NULL;
3459         }
3460
3461         mymiplevel = savemiplevel;
3462         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3463         {
3464                 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);
3465 #ifndef USE_GLES2
3466                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3467                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3468 #endif
3469                 Mem_Free(pixels);
3470                 pixels = NULL;
3471         }
3472
3473         mymiplevel = savemiplevel;
3474         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3475         {
3476                 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);
3477 #ifndef USE_GLES2
3478                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3479                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3480 #endif
3481                 Mem_Free(pixels);
3482                 pixels = NULL;
3483         }
3484
3485         mymiplevel = savemiplevel;
3486         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3487         {
3488                 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);
3489 #ifndef USE_GLES2
3490                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3491                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3492 #endif
3493                 Mem_Free(pixels);
3494                 pixels = NULL;
3495         }
3496
3497         mymiplevel = savemiplevel;
3498         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3499         {
3500                 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);
3501 #ifndef USE_GLES2
3502                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3503                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3504 #endif
3505                 Mem_Free(pixels);
3506                 pixels = NULL;
3507         }
3508
3509         if (basepixels)
3510                 Mem_Free(basepixels);
3511
3512         return skinframe;
3513 }
3514
3515 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3516 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3517 {
3518         int i;
3519         unsigned char *temp1, *temp2;
3520         skinframe_t *skinframe;
3521
3522         if (cls.state == ca_dedicated)
3523                 return NULL;
3524
3525         // if already loaded just return it, otherwise make a new skinframe
3526         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3527         if (skinframe && skinframe->base)
3528                 return skinframe;
3529         textureflags &= ~TEXF_FORCE_RELOAD;
3530
3531         skinframe->stain = NULL;
3532         skinframe->merged = NULL;
3533         skinframe->base = NULL;
3534         skinframe->pants = NULL;
3535         skinframe->shirt = NULL;
3536         skinframe->nmap = NULL;
3537         skinframe->gloss = NULL;
3538         skinframe->glow = NULL;
3539         skinframe->fog = NULL;
3540         skinframe->reflect = NULL;
3541         skinframe->hasalpha = false;
3542
3543         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3544         if (!skindata)
3545                 return NULL;
3546
3547         if (developer_loading.integer)
3548                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3549
3550         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3551         {
3552                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3553                 temp2 = temp1 + width * height * 4;
3554                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3555                 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);
3556                 Mem_Free(temp1);
3557         }
3558         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3559         if (textureflags & TEXF_ALPHA)
3560         {
3561                 for (i = 3;i < width * height * 4;i += 4)
3562                 {
3563                         if (skindata[i] < 255)
3564                         {
3565                                 skinframe->hasalpha = true;
3566                                 break;
3567                         }
3568                 }
3569                 if (r_loadfog && skinframe->hasalpha)
3570                 {
3571                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3572                         memcpy(fogpixels, skindata, width * height * 4);
3573                         for (i = 0;i < width * height * 4;i += 4)
3574                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3575                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3576                         Mem_Free(fogpixels);
3577                 }
3578         }
3579
3580         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3581         //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]);
3582
3583         return skinframe;
3584 }
3585
3586 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3587 {
3588         int i;
3589         int featuresmask;
3590         skinframe_t *skinframe;
3591
3592         if (cls.state == ca_dedicated)
3593                 return NULL;
3594
3595         // if already loaded just return it, otherwise make a new skinframe
3596         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3597         if (skinframe && skinframe->base)
3598                 return skinframe;
3599         textureflags &= ~TEXF_FORCE_RELOAD;
3600
3601         skinframe->stain = NULL;
3602         skinframe->merged = NULL;
3603         skinframe->base = NULL;
3604         skinframe->pants = NULL;
3605         skinframe->shirt = NULL;
3606         skinframe->nmap = NULL;
3607         skinframe->gloss = NULL;
3608         skinframe->glow = NULL;
3609         skinframe->fog = NULL;
3610         skinframe->reflect = NULL;
3611         skinframe->hasalpha = false;
3612
3613         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3614         if (!skindata)
3615                 return NULL;
3616
3617         if (developer_loading.integer)
3618                 Con_Printf("loading quake skin \"%s\"\n", name);
3619
3620         // 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)
3621         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3622         memcpy(skinframe->qpixels, skindata, width*height);
3623         skinframe->qwidth = width;
3624         skinframe->qheight = height;
3625
3626         featuresmask = 0;
3627         for (i = 0;i < width * height;i++)
3628                 featuresmask |= palette_featureflags[skindata[i]];
3629
3630         skinframe->hasalpha = false;
3631         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3632         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3633         skinframe->qgeneratemerged = true;
3634         skinframe->qgeneratebase = skinframe->qhascolormapping;
3635         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3636
3637         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3638         //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]);
3639
3640         return skinframe;
3641 }
3642
3643 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3644 {
3645         int width;
3646         int height;
3647         unsigned char *skindata;
3648
3649         if (!skinframe->qpixels)
3650                 return;
3651
3652         if (!skinframe->qhascolormapping)
3653                 colormapped = false;
3654
3655         if (colormapped)
3656         {
3657                 if (!skinframe->qgeneratebase)
3658                         return;
3659         }
3660         else
3661         {
3662                 if (!skinframe->qgeneratemerged)
3663                         return;
3664         }
3665
3666         width = skinframe->qwidth;
3667         height = skinframe->qheight;
3668         skindata = skinframe->qpixels;
3669
3670         if (skinframe->qgeneratenmap)
3671         {
3672                 unsigned char *temp1, *temp2;
3673                 skinframe->qgeneratenmap = false;
3674                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3675                 temp2 = temp1 + width * height * 4;
3676                 // use either a custom palette or the quake palette
3677                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3678                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3679                 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);
3680                 Mem_Free(temp1);
3681         }
3682
3683         if (skinframe->qgenerateglow)
3684         {
3685                 skinframe->qgenerateglow = false;
3686                 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
3687         }
3688
3689         if (colormapped)
3690         {
3691                 skinframe->qgeneratebase = false;
3692                 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);
3693                 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);
3694                 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);
3695         }
3696         else
3697         {
3698                 skinframe->qgeneratemerged = false;
3699                 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);
3700         }
3701
3702         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3703         {
3704                 Mem_Free(skinframe->qpixels);
3705                 skinframe->qpixels = NULL;
3706         }
3707 }
3708
3709 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)
3710 {
3711         int i;
3712         skinframe_t *skinframe;
3713
3714         if (cls.state == ca_dedicated)
3715                 return NULL;
3716
3717         // if already loaded just return it, otherwise make a new skinframe
3718         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3719         if (skinframe && skinframe->base)
3720                 return skinframe;
3721         textureflags &= ~TEXF_FORCE_RELOAD;
3722
3723         skinframe->stain = NULL;
3724         skinframe->merged = NULL;
3725         skinframe->base = NULL;
3726         skinframe->pants = NULL;
3727         skinframe->shirt = NULL;
3728         skinframe->nmap = NULL;
3729         skinframe->gloss = NULL;
3730         skinframe->glow = NULL;
3731         skinframe->fog = NULL;
3732         skinframe->reflect = NULL;
3733         skinframe->hasalpha = false;
3734
3735         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3736         if (!skindata)
3737                 return NULL;
3738
3739         if (developer_loading.integer)
3740                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3741
3742         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3743         if (textureflags & TEXF_ALPHA)
3744         {
3745                 for (i = 0;i < width * height;i++)
3746                 {
3747                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3748                         {
3749                                 skinframe->hasalpha = true;
3750                                 break;
3751                         }
3752                 }
3753                 if (r_loadfog && skinframe->hasalpha)
3754                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3755         }
3756
3757         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3758         //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]);
3759
3760         return skinframe;
3761 }
3762
3763 skinframe_t *R_SkinFrame_LoadMissing(void)
3764 {
3765         skinframe_t *skinframe;
3766
3767         if (cls.state == ca_dedicated)
3768                 return NULL;
3769
3770         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3771         skinframe->stain = NULL;
3772         skinframe->merged = NULL;
3773         skinframe->base = NULL;
3774         skinframe->pants = NULL;
3775         skinframe->shirt = NULL;
3776         skinframe->nmap = NULL;
3777         skinframe->gloss = NULL;
3778         skinframe->glow = NULL;
3779         skinframe->fog = NULL;
3780         skinframe->reflect = NULL;
3781         skinframe->hasalpha = false;
3782
3783         skinframe->avgcolor[0] = rand() / RAND_MAX;
3784         skinframe->avgcolor[1] = rand() / RAND_MAX;
3785         skinframe->avgcolor[2] = rand() / RAND_MAX;
3786         skinframe->avgcolor[3] = 1;
3787
3788         return skinframe;
3789 }
3790
3791 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3792 typedef struct suffixinfo_s
3793 {
3794         const char *suffix;
3795         qboolean flipx, flipy, flipdiagonal;
3796 }
3797 suffixinfo_t;
3798 static suffixinfo_t suffix[3][6] =
3799 {
3800         {
3801                 {"px",   false, false, false},
3802                 {"nx",   false, false, false},
3803                 {"py",   false, false, false},
3804                 {"ny",   false, false, false},
3805                 {"pz",   false, false, false},
3806                 {"nz",   false, false, false}
3807         },
3808         {
3809                 {"posx", false, false, false},
3810                 {"negx", false, false, false},
3811                 {"posy", false, false, false},
3812                 {"negy", false, false, false},
3813                 {"posz", false, false, false},
3814                 {"negz", false, false, false}
3815         },
3816         {
3817                 {"rt",    true, false,  true},
3818                 {"lf",   false,  true,  true},
3819                 {"ft",    true,  true, false},
3820                 {"bk",   false, false, false},
3821                 {"up",    true, false,  true},
3822                 {"dn",    true, false,  true}
3823         }
3824 };
3825
3826 static int componentorder[4] = {0, 1, 2, 3};
3827
3828 rtexture_t *R_LoadCubemap(const char *basename)
3829 {
3830         int i, j, cubemapsize;
3831         unsigned char *cubemappixels, *image_buffer;
3832         rtexture_t *cubemaptexture;
3833         char name[256];
3834         // must start 0 so the first loadimagepixels has no requested width/height
3835         cubemapsize = 0;
3836         cubemappixels = NULL;
3837         cubemaptexture = NULL;
3838         // keep trying different suffix groups (posx, px, rt) until one loads
3839         for (j = 0;j < 3 && !cubemappixels;j++)
3840         {
3841                 // load the 6 images in the suffix group
3842                 for (i = 0;i < 6;i++)
3843                 {
3844                         // generate an image name based on the base and and suffix
3845                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3846                         // load it
3847                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3848                         {
3849                                 // an image loaded, make sure width and height are equal
3850                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3851                                 {
3852                                         // if this is the first image to load successfully, allocate the cubemap memory
3853                                         if (!cubemappixels && image_width >= 1)
3854                                         {
3855                                                 cubemapsize = image_width;
3856                                                 // note this clears to black, so unavailable sides are black
3857                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3858                                         }
3859                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3860                                         if (cubemappixels)
3861                                                 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);
3862                                 }
3863                                 else
3864                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3865                                 // free the image
3866                                 Mem_Free(image_buffer);
3867                         }
3868                 }
3869         }
3870         // if a cubemap loaded, upload it
3871         if (cubemappixels)
3872         {
3873                 if (developer_loading.integer)
3874                         Con_Printf("loading cubemap \"%s\"\n", basename);
3875
3876                 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);
3877                 Mem_Free(cubemappixels);
3878         }
3879         else
3880         {
3881                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3882                 if (developer_loading.integer)
3883                 {
3884                         Con_Printf("(tried tried images ");
3885                         for (j = 0;j < 3;j++)
3886                                 for (i = 0;i < 6;i++)
3887                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3888                         Con_Print(" and was unable to find any of them).\n");
3889                 }
3890         }
3891         return cubemaptexture;
3892 }
3893
3894 rtexture_t *R_GetCubemap(const char *basename)
3895 {
3896         int i;
3897         for (i = 0;i < r_texture_numcubemaps;i++)
3898                 if (r_texture_cubemaps[i] != NULL)
3899                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3900                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3901         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3902                 return r_texture_whitecube;
3903         r_texture_numcubemaps++;
3904         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3905         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3906         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3907         return r_texture_cubemaps[i]->texture;
3908 }
3909
3910 void R_FreeCubemap(const char *basename)
3911 {
3912         int i;
3913
3914         for (i = 0;i < r_texture_numcubemaps;i++)
3915         {
3916                 if (r_texture_cubemaps[i] != NULL)
3917                 {
3918                         if (r_texture_cubemaps[i]->texture)
3919                         {
3920                                 if (developer_loading.integer)
3921                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3922                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3923                                 Mem_Free(r_texture_cubemaps[i]);
3924                                 r_texture_cubemaps[i] = NULL;
3925                         }
3926                 }
3927         }
3928 }
3929
3930 void R_FreeCubemaps(void)
3931 {
3932         int i;
3933         for (i = 0;i < r_texture_numcubemaps;i++)
3934         {
3935                 if (developer_loading.integer)
3936                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3937                 if (r_texture_cubemaps[i] != NULL)
3938                 {
3939                         if (r_texture_cubemaps[i]->texture)
3940                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3941                         Mem_Free(r_texture_cubemaps[i]);
3942                 }
3943         }
3944         r_texture_numcubemaps = 0;
3945 }
3946
3947 void R_Main_FreeViewCache(void)
3948 {
3949         if (r_refdef.viewcache.entityvisible)
3950                 Mem_Free(r_refdef.viewcache.entityvisible);
3951         if (r_refdef.viewcache.world_pvsbits)
3952                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3953         if (r_refdef.viewcache.world_leafvisible)
3954                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3955         if (r_refdef.viewcache.world_surfacevisible)
3956                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3957         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3958 }
3959
3960 void R_Main_ResizeViewCache(void)
3961 {
3962         int numentities = r_refdef.scene.numentities;
3963         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3964         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3965         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3966         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3967         if (r_refdef.viewcache.maxentities < numentities)
3968         {
3969                 r_refdef.viewcache.maxentities = numentities;
3970                 if (r_refdef.viewcache.entityvisible)
3971                         Mem_Free(r_refdef.viewcache.entityvisible);
3972                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3973         }
3974         if (r_refdef.viewcache.world_numclusters != numclusters)
3975         {
3976                 r_refdef.viewcache.world_numclusters = numclusters;
3977                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3978                 if (r_refdef.viewcache.world_pvsbits)
3979                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3980                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3981         }
3982         if (r_refdef.viewcache.world_numleafs != numleafs)
3983         {
3984                 r_refdef.viewcache.world_numleafs = numleafs;
3985                 if (r_refdef.viewcache.world_leafvisible)
3986                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3987                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3988         }
3989         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3990         {
3991                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3992                 if (r_refdef.viewcache.world_surfacevisible)
3993                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3994                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3995         }
3996 }
3997
3998 extern rtexture_t *loadingscreentexture;
3999 void gl_main_start(void)
4000 {
4001         loadingscreentexture = NULL;
4002         r_texture_blanknormalmap = NULL;
4003         r_texture_white = NULL;
4004         r_texture_grey128 = NULL;
4005         r_texture_black = NULL;
4006         r_texture_whitecube = NULL;
4007         r_texture_normalizationcube = NULL;
4008         r_texture_fogattenuation = NULL;
4009         r_texture_fogheighttexture = NULL;
4010         r_texture_gammaramps = NULL;
4011         r_texture_numcubemaps = 0;
4012
4013         r_loaddds = r_texture_dds_load.integer != 0;
4014         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4015
4016         switch(vid.renderpath)
4017         {
4018         case RENDERPATH_GL20:
4019         case RENDERPATH_D3D9:
4020         case RENDERPATH_D3D10:
4021         case RENDERPATH_D3D11:
4022         case RENDERPATH_SOFT:
4023         case RENDERPATH_GLES2:
4024                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4025                 Cvar_SetValueQuick(&gl_combine, 1);
4026                 Cvar_SetValueQuick(&r_glsl, 1);
4027                 r_loadnormalmap = true;
4028                 r_loadgloss = true;
4029                 r_loadfog = false;
4030                 break;
4031         case RENDERPATH_GL13:
4032         case RENDERPATH_GLES1:
4033                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4034                 Cvar_SetValueQuick(&gl_combine, 1);
4035                 Cvar_SetValueQuick(&r_glsl, 0);
4036                 r_loadnormalmap = false;
4037                 r_loadgloss = false;
4038                 r_loadfog = true;
4039                 break;
4040         case RENDERPATH_GL11:
4041                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4042                 Cvar_SetValueQuick(&gl_combine, 0);
4043                 Cvar_SetValueQuick(&r_glsl, 0);
4044                 r_loadnormalmap = false;
4045                 r_loadgloss = false;
4046                 r_loadfog = true;
4047                 break;
4048         }
4049
4050         R_AnimCache_Free();
4051         R_FrameData_Reset();
4052
4053         r_numqueries = 0;
4054         r_maxqueries = 0;
4055         memset(r_queries, 0, sizeof(r_queries));
4056
4057         r_qwskincache = NULL;
4058         r_qwskincache_size = 0;
4059
4060         // due to caching of texture_t references, the collision cache must be reset
4061         Collision_Cache_Reset(true);
4062
4063         // set up r_skinframe loading system for textures
4064         memset(&r_skinframe, 0, sizeof(r_skinframe));
4065         r_skinframe.loadsequence = 1;
4066         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4067
4068         r_main_texturepool = R_AllocTexturePool();
4069         R_BuildBlankTextures();
4070         R_BuildNoTexture();
4071         if (vid.support.arb_texture_cube_map)
4072         {
4073                 R_BuildWhiteCube();
4074                 R_BuildNormalizationCube();
4075         }
4076         r_texture_fogattenuation = NULL;
4077         r_texture_fogheighttexture = NULL;
4078         r_texture_gammaramps = NULL;
4079         //r_texture_fogintensity = NULL;
4080         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4081         memset(&r_waterstate, 0, sizeof(r_waterstate));
4082         r_glsl_permutation = NULL;
4083         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4084         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4085         glslshaderstring = NULL;
4086 #ifdef SUPPORTD3D
4087         r_hlsl_permutation = NULL;
4088         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4089         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4090 #endif
4091         hlslshaderstring = NULL;
4092         memset(&r_svbsp, 0, sizeof (r_svbsp));
4093
4094         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4095         r_texture_numcubemaps = 0;
4096
4097         r_refdef.fogmasktable_density = 0;
4098 }
4099
4100 void gl_main_shutdown(void)
4101 {
4102         R_AnimCache_Free();
4103         R_FrameData_Reset();
4104
4105         R_Main_FreeViewCache();
4106
4107         switch(vid.renderpath)
4108         {
4109         case RENDERPATH_GL11:
4110         case RENDERPATH_GL13:
4111         case RENDERPATH_GL20:
4112         case RENDERPATH_GLES1:
4113         case RENDERPATH_GLES2:
4114 #ifdef GL_SAMPLES_PASSED_ARB
4115                 if (r_maxqueries)
4116                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4117 #endif
4118                 break;
4119         case RENDERPATH_D3D9:
4120                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4121                 break;
4122         case RENDERPATH_D3D10:
4123                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4124                 break;
4125         case RENDERPATH_D3D11:
4126                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4127                 break;
4128         case RENDERPATH_SOFT:
4129                 break;
4130         }
4131
4132         r_numqueries = 0;
4133         r_maxqueries = 0;
4134         memset(r_queries, 0, sizeof(r_queries));
4135
4136         r_qwskincache = NULL;
4137         r_qwskincache_size = 0;
4138
4139         // clear out the r_skinframe state
4140         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4141         memset(&r_skinframe, 0, sizeof(r_skinframe));
4142
4143         if (r_svbsp.nodes)
4144                 Mem_Free(r_svbsp.nodes);
4145         memset(&r_svbsp, 0, sizeof (r_svbsp));
4146         R_FreeTexturePool(&r_main_texturepool);
4147         loadingscreentexture = NULL;
4148         r_texture_blanknormalmap = NULL;
4149         r_texture_white = NULL;
4150         r_texture_grey128 = NULL;
4151         r_texture_black = NULL;
4152         r_texture_whitecube = NULL;
4153         r_texture_normalizationcube = NULL;
4154         r_texture_fogattenuation = NULL;
4155         r_texture_fogheighttexture = NULL;
4156         r_texture_gammaramps = NULL;
4157         r_texture_numcubemaps = 0;
4158         //r_texture_fogintensity = NULL;
4159         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4160         memset(&r_waterstate, 0, sizeof(r_waterstate));
4161         R_GLSL_Restart_f();
4162
4163         r_glsl_permutation = NULL;
4164         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4165         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4166         glslshaderstring = NULL;
4167 #ifdef SUPPORTD3D
4168         r_hlsl_permutation = NULL;
4169         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4170         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4171 #endif
4172         hlslshaderstring = NULL;
4173 }
4174
4175 extern void CL_ParseEntityLump(char *entitystring);
4176 void gl_main_newmap(void)
4177 {
4178         // FIXME: move this code to client
4179         char *entities, entname[MAX_QPATH];
4180         if (r_qwskincache)
4181                 Mem_Free(r_qwskincache);
4182         r_qwskincache = NULL;
4183         r_qwskincache_size = 0;
4184         if (cl.worldmodel)
4185         {
4186                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4187                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4188                 {
4189                         CL_ParseEntityLump(entities);
4190                         Mem_Free(entities);
4191                         return;
4192                 }
4193                 if (cl.worldmodel->brush.entities)
4194                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4195         }
4196         R_Main_FreeViewCache();
4197
4198         R_FrameData_Reset();
4199 }
4200
4201 void GL_Main_Init(void)
4202 {
4203         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4204
4205         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4206         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4207         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4208         if (gamemode == GAME_NEHAHRA)
4209         {
4210                 Cvar_RegisterVariable (&gl_fogenable);
4211                 Cvar_RegisterVariable (&gl_fogdensity);
4212                 Cvar_RegisterVariable (&gl_fogred);
4213                 Cvar_RegisterVariable (&gl_foggreen);
4214                 Cvar_RegisterVariable (&gl_fogblue);
4215                 Cvar_RegisterVariable (&gl_fogstart);
4216                 Cvar_RegisterVariable (&gl_fogend);
4217                 Cvar_RegisterVariable (&gl_skyclip);
4218         }
4219         Cvar_RegisterVariable(&r_motionblur);
4220         Cvar_RegisterVariable(&r_damageblur);
4221         Cvar_RegisterVariable(&r_motionblur_averaging);
4222         Cvar_RegisterVariable(&r_motionblur_randomize);
4223         Cvar_RegisterVariable(&r_motionblur_minblur);
4224         Cvar_RegisterVariable(&r_motionblur_maxblur);
4225         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4226         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4227         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4228         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4229         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4230         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4231         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4232         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4233         Cvar_RegisterVariable(&r_equalize_entities_by);
4234         Cvar_RegisterVariable(&r_equalize_entities_to);
4235         Cvar_RegisterVariable(&r_depthfirst);
4236         Cvar_RegisterVariable(&r_useinfinitefarclip);
4237         Cvar_RegisterVariable(&r_farclip_base);
4238         Cvar_RegisterVariable(&r_farclip_world);
4239         Cvar_RegisterVariable(&r_nearclip);
4240         Cvar_RegisterVariable(&r_deformvertexes);
4241         Cvar_RegisterVariable(&r_transparent);
4242         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4243         Cvar_RegisterVariable(&r_showoverdraw);
4244         Cvar_RegisterVariable(&r_showbboxes);
4245         Cvar_RegisterVariable(&r_showsurfaces);
4246         Cvar_RegisterVariable(&r_showtris);
4247         Cvar_RegisterVariable(&r_shownormals);
4248         Cvar_RegisterVariable(&r_showlighting);
4249         Cvar_RegisterVariable(&r_showshadowvolumes);
4250         Cvar_RegisterVariable(&r_showcollisionbrushes);
4251         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4252         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4253         Cvar_RegisterVariable(&r_showdisabledepthtest);
4254         Cvar_RegisterVariable(&r_drawportals);
4255         Cvar_RegisterVariable(&r_drawentities);
4256         Cvar_RegisterVariable(&r_draw2d);
4257         Cvar_RegisterVariable(&r_drawworld);
4258         Cvar_RegisterVariable(&r_cullentities_trace);
4259         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4260         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4261         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4262         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4263         Cvar_RegisterVariable(&r_sortentities);
4264         Cvar_RegisterVariable(&r_drawviewmodel);
4265         Cvar_RegisterVariable(&r_drawexteriormodel);
4266         Cvar_RegisterVariable(&r_speeds);
4267         Cvar_RegisterVariable(&r_fullbrights);
4268         Cvar_RegisterVariable(&r_wateralpha);
4269         Cvar_RegisterVariable(&r_dynamic);
4270         Cvar_RegisterVariable(&r_fakelight);
4271         Cvar_RegisterVariable(&r_fakelight_intensity);
4272         Cvar_RegisterVariable(&r_fullbright);
4273         Cvar_RegisterVariable(&r_shadows);
4274         Cvar_RegisterVariable(&r_shadows_darken);
4275         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4276         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4277         Cvar_RegisterVariable(&r_shadows_throwdistance);
4278         Cvar_RegisterVariable(&r_shadows_throwdirection);
4279         Cvar_RegisterVariable(&r_shadows_focus);
4280         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4281         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4282         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4283         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4284         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4285         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4286         Cvar_RegisterVariable(&r_fog_exp2);
4287         Cvar_RegisterVariable(&r_fog_clear);
4288         Cvar_RegisterVariable(&r_drawfog);
4289         Cvar_RegisterVariable(&r_transparentdepthmasking);
4290         Cvar_RegisterVariable(&r_transparent_sortmindist);
4291         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4292         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4293         Cvar_RegisterVariable(&r_texture_dds_load);
4294         Cvar_RegisterVariable(&r_texture_dds_save);
4295         Cvar_RegisterVariable(&r_textureunits);
4296         Cvar_RegisterVariable(&gl_combine);
4297         Cvar_RegisterVariable(&r_viewfbo);
4298         Cvar_RegisterVariable(&r_viewscale);
4299         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4300         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4301         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4302         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4303         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4304         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4305         Cvar_RegisterVariable(&r_glsl);
4306         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4307         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4308         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4309         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4310         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4311         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4312         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4313         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4314         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4315         Cvar_RegisterVariable(&r_glsl_postprocess);
4316         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4317         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4318         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4319         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4320         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4321         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4322         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4323         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4324
4325         Cvar_RegisterVariable(&r_water);
4326         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4327         Cvar_RegisterVariable(&r_water_clippingplanebias);
4328         Cvar_RegisterVariable(&r_water_refractdistort);
4329         Cvar_RegisterVariable(&r_water_reflectdistort);
4330         Cvar_RegisterVariable(&r_water_scissormode);
4331         Cvar_RegisterVariable(&r_water_lowquality);
4332
4333         Cvar_RegisterVariable(&r_lerpsprites);
4334         Cvar_RegisterVariable(&r_lerpmodels);
4335         Cvar_RegisterVariable(&r_lerplightstyles);
4336         Cvar_RegisterVariable(&r_waterscroll);
4337         Cvar_RegisterVariable(&r_bloom);
4338         Cvar_RegisterVariable(&r_bloom_colorscale);
4339         Cvar_RegisterVariable(&r_bloom_brighten);
4340         Cvar_RegisterVariable(&r_bloom_blur);
4341         Cvar_RegisterVariable(&r_bloom_resolution);
4342         Cvar_RegisterVariable(&r_bloom_colorexponent);
4343         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4344         Cvar_RegisterVariable(&r_hdr);
4345         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4346         Cvar_RegisterVariable(&r_hdr_glowintensity);
4347         Cvar_RegisterVariable(&r_hdr_range);
4348         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4349         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4350         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4351         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4352         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4353         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4354         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4355         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4356         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4357         Cvar_RegisterVariable(&developer_texturelogging);
4358         Cvar_RegisterVariable(&gl_lightmaps);
4359         Cvar_RegisterVariable(&r_test);
4360         Cvar_RegisterVariable(&r_glsl_saturation);
4361         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4362         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4363         Cvar_RegisterVariable(&r_framedatasize);
4364         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4365                 Cvar_SetValue("r_fullbrights", 0);
4366         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4367 }
4368
4369 extern void R_Textures_Init(void);
4370 extern void GL_Draw_Init(void);
4371 extern void GL_Main_Init(void);
4372 extern void R_Shadow_Init(void);
4373 extern void R_Sky_Init(void);
4374 extern void GL_Surf_Init(void);
4375 extern void R_Particles_Init(void);
4376 extern void R_Explosion_Init(void);
4377 extern void gl_backend_init(void);
4378 extern void Sbar_Init(void);
4379 extern void R_LightningBeams_Init(void);
4380 extern void Mod_RenderInit(void);
4381 extern void Font_Init(void);
4382
4383 void Render_Init(void)
4384 {
4385         gl_backend_init();
4386         R_Textures_Init();
4387         GL_Main_Init();
4388         Font_Init();
4389         GL_Draw_Init();
4390         R_Shadow_Init();
4391         R_Sky_Init();
4392         GL_Surf_Init();
4393         Sbar_Init();
4394         R_Particles_Init();
4395         R_Explosion_Init();
4396         R_LightningBeams_Init();
4397         Mod_RenderInit();
4398 }
4399
4400 /*
4401 ===============
4402 GL_Init
4403 ===============
4404 */
4405 #ifndef USE_GLES2
4406 extern char *ENGINE_EXTENSIONS;
4407 void GL_Init (void)
4408 {
4409         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4410         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4411         gl_version = (const char *)qglGetString(GL_VERSION);
4412         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4413
4414         if (!gl_extensions)
4415                 gl_extensions = "";
4416         if (!gl_platformextensions)
4417                 gl_platformextensions = "";
4418
4419         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4420         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4421         Con_Printf("GL_VERSION: %s\n", gl_version);
4422         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4423         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4424
4425         VID_CheckExtensions();
4426
4427         // LordHavoc: report supported extensions
4428         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4429
4430         // clear to black (loading plaque will be seen over this)
4431         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4432 }
4433 #endif
4434
4435 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4436 {
4437         int i;
4438         mplane_t *p;
4439         if (r_trippy.integer)
4440                 return false;
4441         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4442         {
4443                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4444                 if (i == 4)
4445                         continue;
4446                 p = r_refdef.view.frustum + i;
4447                 switch(p->signbits)
4448                 {
4449                 default:
4450                 case 0:
4451                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4452                                 return true;
4453                         break;
4454                 case 1:
4455                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4456                                 return true;
4457                         break;
4458                 case 2:
4459                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4460                                 return true;
4461                         break;
4462                 case 3:
4463                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4464                                 return true;
4465                         break;
4466                 case 4:
4467                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4468                                 return true;
4469                         break;
4470                 case 5:
4471                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4472                                 return true;
4473                         break;
4474                 case 6:
4475                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 case 7:
4479                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 }
4483         }
4484         return false;
4485 }
4486
4487 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4488 {
4489         int i;
4490         const mplane_t *p;
4491         if (r_trippy.integer)
4492                 return false;
4493         for (i = 0;i < numplanes;i++)
4494         {
4495                 p = planes + i;
4496                 switch(p->signbits)
4497                 {
4498                 default:
4499                 case 0:
4500                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 1:
4504                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 case 2:
4508                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4509                                 return true;
4510                         break;
4511                 case 3:
4512                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4513                                 return true;
4514                         break;
4515                 case 4:
4516                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4517                                 return true;
4518                         break;
4519                 case 5:
4520                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4521                                 return true;
4522                         break;
4523                 case 6:
4524                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4525                                 return true;
4526                         break;
4527                 case 7:
4528                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4529                                 return true;
4530                         break;
4531                 }
4532         }
4533         return false;
4534 }
4535
4536 //==================================================================================
4537
4538 // LordHavoc: this stores temporary data used within the same frame
4539
4540 typedef struct r_framedata_mem_s
4541 {
4542         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4543         size_t size; // how much usable space
4544         size_t current; // how much space in use
4545         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4546         size_t wantedsize; // how much space was allocated
4547         unsigned char *data; // start of real data (16byte aligned)
4548 }
4549 r_framedata_mem_t;
4550
4551 static r_framedata_mem_t *r_framedata_mem;
4552
4553 void R_FrameData_Reset(void)
4554 {
4555         while (r_framedata_mem)
4556         {
4557                 r_framedata_mem_t *next = r_framedata_mem->purge;
4558                 Mem_Free(r_framedata_mem);
4559                 r_framedata_mem = next;
4560         }
4561 }
4562
4563 void R_FrameData_Resize(void)
4564 {
4565         size_t wantedsize;
4566         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4567         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4568         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4569         {
4570                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4571                 newmem->wantedsize = wantedsize;
4572                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4573                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4574                 newmem->current = 0;
4575                 newmem->mark = 0;
4576                 newmem->purge = r_framedata_mem;
4577                 r_framedata_mem = newmem;
4578         }
4579 }
4580
4581 void R_FrameData_NewFrame(void)
4582 {
4583         R_FrameData_Resize();
4584         if (!r_framedata_mem)
4585                 return;
4586         // if we ran out of space on the last frame, free the old memory now
4587         while (r_framedata_mem->purge)
4588         {
4589                 // repeatedly remove the second item in the list, leaving only head
4590                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4591                 Mem_Free(r_framedata_mem->purge);
4592                 r_framedata_mem->purge = next;
4593         }
4594         // reset the current mem pointer
4595         r_framedata_mem->current = 0;
4596         r_framedata_mem->mark = 0;
4597 }
4598
4599 void *R_FrameData_Alloc(size_t size)
4600 {
4601         void *data;
4602
4603         // align to 16 byte boundary - the data pointer is already aligned, so we
4604         // only need to ensure the size of every allocation is also aligned
4605         size = (size + 15) & ~15;
4606
4607         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4608         {
4609                 // emergency - we ran out of space, allocate more memory
4610                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4611                 R_FrameData_Resize();
4612         }
4613
4614         data = r_framedata_mem->data + r_framedata_mem->current;
4615         r_framedata_mem->current += size;
4616
4617         // count the usage for stats
4618         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4619         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4620
4621         return (void *)data;
4622 }
4623
4624 void *R_FrameData_Store(size_t size, void *data)
4625 {
4626         void *d = R_FrameData_Alloc(size);
4627         if (d && data)
4628                 memcpy(d, data, size);
4629         return d;
4630 }
4631
4632 void R_FrameData_SetMark(void)
4633 {
4634         if (!r_framedata_mem)
4635                 return;
4636         r_framedata_mem->mark = r_framedata_mem->current;
4637 }
4638
4639 void R_FrameData_ReturnToMark(void)
4640 {
4641         if (!r_framedata_mem)
4642                 return;
4643         r_framedata_mem->current = r_framedata_mem->mark;
4644 }
4645
4646 //==================================================================================
4647
4648 // LordHavoc: animcache originally written by Echon, rewritten since then
4649
4650 /**
4651  * Animation cache prevents re-generating mesh data for an animated model
4652  * multiple times in one frame for lighting, shadowing, reflections, etc.
4653  */
4654
4655 void R_AnimCache_Free(void)
4656 {
4657 }
4658
4659 void R_AnimCache_ClearCache(void)
4660 {
4661         int i;
4662         entity_render_t *ent;
4663
4664         for (i = 0;i < r_refdef.scene.numentities;i++)
4665         {
4666                 ent = r_refdef.scene.entities[i];
4667                 ent->animcache_vertex3f = NULL;
4668                 ent->animcache_normal3f = NULL;
4669                 ent->animcache_svector3f = NULL;
4670                 ent->animcache_tvector3f = NULL;
4671                 ent->animcache_vertexmesh = NULL;
4672                 ent->animcache_vertex3fbuffer = NULL;
4673                 ent->animcache_vertexmeshbuffer = NULL;
4674         }
4675 }
4676
4677 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4678 {
4679         int i;
4680
4681         // check if we need the meshbuffers
4682         if (!vid.useinterleavedarrays)
4683                 return;
4684
4685         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4686                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4687         // TODO: upload vertex3f buffer?
4688         if (ent->animcache_vertexmesh)
4689         {
4690                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4691                 for (i = 0;i < numvertices;i++)
4692                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4693                 if (ent->animcache_svector3f)
4694                         for (i = 0;i < numvertices;i++)
4695                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4696                 if (ent->animcache_tvector3f)
4697                         for (i = 0;i < numvertices;i++)
4698                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4699                 if (ent->animcache_normal3f)
4700                         for (i = 0;i < numvertices;i++)
4701                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4702                 // TODO: upload vertexmeshbuffer?
4703         }
4704 }
4705
4706 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4707 {
4708         dp_model_t *model = ent->model;
4709         int numvertices;
4710         // see if it's already cached this frame
4711         if (ent->animcache_vertex3f)
4712         {
4713                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4714                 if (wantnormals || wanttangents)
4715                 {
4716                         if (ent->animcache_normal3f)
4717                                 wantnormals = false;
4718                         if (ent->animcache_svector3f)
4719                                 wanttangents = false;
4720                         if (wantnormals || wanttangents)
4721                         {
4722                                 numvertices = model->surfmesh.num_vertices;
4723                                 if (wantnormals)
4724                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4725                                 if (wanttangents)
4726                                 {
4727                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4728                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4729                                 }
4730                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4731                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4732                         }
4733                 }
4734         }
4735         else
4736         {
4737                 // see if this ent is worth caching
4738                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4739                         return false;
4740                 // get some memory for this entity and generate mesh data
4741                 numvertices = model->surfmesh.num_vertices;
4742                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4743                 if (wantnormals)
4744                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4745                 if (wanttangents)
4746                 {
4747                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4748                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4749                 }
4750                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4751                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4752         }
4753         return true;
4754 }
4755
4756 void R_AnimCache_CacheVisibleEntities(void)
4757 {
4758         int i;
4759         qboolean wantnormals = true;
4760         qboolean wanttangents = !r_showsurfaces.integer;
4761
4762         switch(vid.renderpath)
4763         {
4764         case RENDERPATH_GL20:
4765         case RENDERPATH_D3D9:
4766         case RENDERPATH_D3D10:
4767         case RENDERPATH_D3D11:
4768         case RENDERPATH_GLES2:
4769                 break;
4770         case RENDERPATH_GL11:
4771         case RENDERPATH_GL13:
4772         case RENDERPATH_GLES1:
4773                 wanttangents = false;
4774                 break;
4775         case RENDERPATH_SOFT:
4776                 break;
4777         }
4778
4779         if (r_shownormals.integer)
4780                 wanttangents = wantnormals = true;
4781
4782         // TODO: thread this
4783         // NOTE: R_PrepareRTLights() also caches entities
4784
4785         for (i = 0;i < r_refdef.scene.numentities;i++)
4786                 if (r_refdef.viewcache.entityvisible[i])
4787                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4788 }
4789
4790 //==================================================================================
4791
4792 extern cvar_t r_overheadsprites_pushback;
4793
4794 static void R_View_UpdateEntityLighting (void)
4795 {
4796         int i;
4797         entity_render_t *ent;
4798         vec3_t tempdiffusenormal, avg;
4799         vec_t f, fa, fd, fdd;
4800         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4801
4802         for (i = 0;i < r_refdef.scene.numentities;i++)
4803         {
4804                 ent = r_refdef.scene.entities[i];
4805
4806                 // skip unseen models and models that updated by CSQC
4807                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4808                         continue;
4809
4810                 // skip bsp models
4811                 if (ent->model && ent->model->brush.num_leafs)
4812                 {
4813                         // TODO: use modellight for r_ambient settings on world?
4814                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4815                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4816                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4817                         continue;
4818                 }
4819
4820                 // fetch the lighting from the worldmodel data
4821                 VectorClear(ent->modellight_ambient);
4822                 VectorClear(ent->modellight_diffuse);
4823                 VectorClear(tempdiffusenormal);
4824                 if (ent->flags & RENDER_LIGHT)
4825                 {
4826                         vec3_t org;
4827                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4828
4829                         // complete lightning for lit sprites
4830                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4831                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4832                         {
4833                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4834                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4835                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4836                         }
4837                         else
4838                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4839
4840                         if(ent->flags & RENDER_EQUALIZE)
4841                         {
4842                                 // first fix up ambient lighting...
4843                                 if(r_equalize_entities_minambient.value > 0)
4844                                 {
4845                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4846                                         if(fd > 0)
4847                                         {
4848                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4849                                                 if(fa < r_equalize_entities_minambient.value * fd)
4850                                                 {
4851                                                         // solve:
4852                                                         //   fa'/fd' = minambient
4853                                                         //   fa'+0.25*fd' = fa+0.25*fd
4854                                                         //   ...
4855                                                         //   fa' = fd' * minambient
4856                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4857                                                         //   ...
4858                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4859                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4860                                                         //   ...
4861                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4862                                                         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
4863                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4864                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4865                                                 }
4866                                         }
4867                                 }
4868
4869                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4870                                 {
4871                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4872                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4873                                         f = fa + 0.25 * fd;
4874                                         if(f > 0)
4875                                         {
4876                                                 // adjust brightness and saturation to target
4877                                                 avg[0] = avg[1] = avg[2] = fa / f;
4878                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4879                                                 avg[0] = avg[1] = avg[2] = fd / f;
4880                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4881                                         }
4882                                 }
4883                         }
4884                 }
4885                 else // highly rare
4886                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4887
4888                 // move the light direction into modelspace coordinates for lighting code
4889                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4890                 if(VectorLength2(ent->modellight_lightdir) == 0)
4891                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4892                 VectorNormalize(ent->modellight_lightdir);
4893         }
4894 }
4895
4896 #define MAX_LINEOFSIGHTTRACES 64
4897
4898 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4899 {
4900         int i;
4901         vec3_t boxmins, boxmaxs;
4902         vec3_t start;
4903         vec3_t end;
4904         dp_model_t *model = r_refdef.scene.worldmodel;
4905
4906         if (!model || !model->brush.TraceLineOfSight)
4907                 return true;
4908
4909         // expand the box a little
4910         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4911         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4912         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4913         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4914         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4915         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4916
4917         // return true if eye is inside enlarged box
4918         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4919                 return true;
4920
4921         // try center
4922         VectorCopy(eye, start);
4923         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4924         if (model->brush.TraceLineOfSight(model, start, end))
4925                 return true;
4926
4927         // try various random positions
4928         for (i = 0;i < numsamples;i++)
4929         {
4930                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4931                 if (model->brush.TraceLineOfSight(model, start, end))
4932                         return true;
4933         }
4934
4935         return false;
4936 }
4937
4938
4939 static void R_View_UpdateEntityVisible (void)
4940 {
4941         int i;
4942         int renderimask;
4943         int samples;
4944         entity_render_t *ent;
4945
4946         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4947                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4948                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4949                 :                                                          RENDER_EXTERIORMODEL;
4950         if (!r_drawviewmodel.integer)
4951                 renderimask |= RENDER_VIEWMODEL;
4952         if (!r_drawexteriormodel.integer)
4953                 renderimask |= RENDER_EXTERIORMODEL;
4954         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4955         {
4956                 // worldmodel can check visibility
4957                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4958                 for (i = 0;i < r_refdef.scene.numentities;i++)
4959                 {
4960                         ent = r_refdef.scene.entities[i];
4961                         if (!(ent->flags & renderimask))
4962                         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)))
4963                         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))
4964                                 r_refdef.viewcache.entityvisible[i] = true;
4965                 }
4966         }
4967         else
4968         {
4969                 // no worldmodel or it can't check visibility
4970                 for (i = 0;i < r_refdef.scene.numentities;i++)
4971                 {
4972                         ent = r_refdef.scene.entities[i];
4973                         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));
4974                 }
4975         }
4976         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4977                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4978         {
4979                 for (i = 0;i < r_refdef.scene.numentities;i++)
4980                 {
4981                         if (!r_refdef.viewcache.entityvisible[i])
4982                                 continue;
4983                         ent = r_refdef.scene.entities[i];
4984                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4985                         {
4986                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4987                                 if (samples < 0)
4988                                         continue; // temp entities do pvs only
4989                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4990                                         ent->last_trace_visibility = realtime;
4991                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4992                                         r_refdef.viewcache.entityvisible[i] = 0;
4993                         }
4994                 }
4995         }
4996 }
4997
4998 /// only used if skyrendermasked, and normally returns false
4999 int R_DrawBrushModelsSky (void)
5000 {
5001         int i, sky;
5002         entity_render_t *ent;
5003
5004         sky = false;
5005         for (i = 0;i < r_refdef.scene.numentities;i++)
5006         {
5007                 if (!r_refdef.viewcache.entityvisible[i])
5008                         continue;
5009                 ent = r_refdef.scene.entities[i];
5010                 if (!ent->model || !ent->model->DrawSky)
5011                         continue;
5012                 ent->model->DrawSky(ent);
5013                 sky = true;
5014         }
5015         return sky;
5016 }
5017
5018 static void R_DrawNoModel(entity_render_t *ent);
5019 static void R_DrawModels(void)
5020 {
5021         int i;
5022         entity_render_t *ent;
5023
5024         for (i = 0;i < r_refdef.scene.numentities;i++)
5025         {
5026                 if (!r_refdef.viewcache.entityvisible[i])
5027                         continue;
5028                 ent = r_refdef.scene.entities[i];
5029                 r_refdef.stats.entities++;
5030                 /*
5031                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5032                 {
5033                         vec3_t f, l, u, o;
5034                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5035                         Con_Printf("R_DrawModels\n");
5036                         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]);
5037                         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);
5038                         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);
5039                 }
5040                 */
5041                 if (ent->model && ent->model->Draw != NULL)
5042                         ent->model->Draw(ent);
5043                 else
5044                         R_DrawNoModel(ent);
5045         }
5046 }
5047
5048 static void R_DrawModelsDepth(void)
5049 {
5050         int i;
5051         entity_render_t *ent;
5052
5053         for (i = 0;i < r_refdef.scene.numentities;i++)
5054         {
5055                 if (!r_refdef.viewcache.entityvisible[i])
5056                         continue;
5057                 ent = r_refdef.scene.entities[i];
5058                 if (ent->model && ent->model->DrawDepth != NULL)
5059                         ent->model->DrawDepth(ent);
5060         }
5061 }
5062
5063 static void R_DrawModelsDebug(void)
5064 {
5065         int i;
5066         entity_render_t *ent;
5067
5068         for (i = 0;i < r_refdef.scene.numentities;i++)
5069         {
5070                 if (!r_refdef.viewcache.entityvisible[i])
5071                         continue;
5072                 ent = r_refdef.scene.entities[i];
5073                 if (ent->model && ent->model->DrawDebug != NULL)
5074                         ent->model->DrawDebug(ent);
5075         }
5076 }
5077
5078 static void R_DrawModelsAddWaterPlanes(void)
5079 {
5080         int i;
5081         entity_render_t *ent;
5082
5083         for (i = 0;i < r_refdef.scene.numentities;i++)
5084         {
5085                 if (!r_refdef.viewcache.entityvisible[i])
5086                         continue;
5087                 ent = r_refdef.scene.entities[i];
5088                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5089                         ent->model->DrawAddWaterPlanes(ent);
5090         }
5091 }
5092
5093 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}};
5094
5095 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5096 {
5097         if (r_hdr_irisadaptation.integer)
5098         {
5099                 vec3_t p;
5100                 vec3_t ambient;
5101                 vec3_t diffuse;
5102                 vec3_t diffusenormal;
5103                 vec3_t forward;
5104                 vec_t brightness = 0.0f;
5105                 vec_t goal;
5106                 vec_t current;
5107                 vec_t d;
5108                 int c;
5109                 VectorCopy(r_refdef.view.forward, forward);
5110                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5111                 {
5112                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5113                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5114                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5115                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5116                         d = DotProduct(forward, diffusenormal);
5117                         brightness += VectorLength(ambient);
5118                         if (d > 0)
5119                                 brightness += d * VectorLength(diffuse);
5120                 }
5121                 brightness *= 1.0f / c;
5122                 brightness += 0.00001f; // make sure it's never zero
5123                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5124                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5125                 current = r_hdr_irisadaptation_value.value;
5126                 if (current < goal)
5127                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5128                 else if (current > goal)
5129                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5130                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5131                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5132         }
5133         else if (r_hdr_irisadaptation_value.value != 1.0f)
5134                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5135 }
5136
5137 static void R_View_SetFrustum(const int *scissor)
5138 {
5139         int i;
5140         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5141         vec3_t forward, left, up, origin, v;
5142
5143         if(scissor)
5144         {
5145                 // flipped x coordinates (because x points left here)
5146                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5147                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5148
5149                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5150                 switch(vid.renderpath)
5151                 {
5152                         case RENDERPATH_D3D9:
5153                         case RENDERPATH_D3D10:
5154                         case RENDERPATH_D3D11:
5155                                 // non-flipped y coordinates
5156                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5157                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5158                                 break;
5159                         case RENDERPATH_SOFT:
5160                         case RENDERPATH_GL11:
5161                         case RENDERPATH_GL13:
5162                         case RENDERPATH_GL20:
5163                         case RENDERPATH_GLES1:
5164                         case RENDERPATH_GLES2:
5165                                 // non-flipped y coordinates
5166                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5167                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5168                                 break;
5169                 }
5170         }
5171
5172         // we can't trust r_refdef.view.forward and friends in reflected scenes
5173         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5174
5175 #if 0
5176         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5177         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5178         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5179         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5180         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5181         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5182         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5183         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5184         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5185         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5186         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5187         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5188 #endif
5189
5190 #if 0
5191         zNear = r_refdef.nearclip;
5192         nudge = 1.0 - 1.0 / (1<<23);
5193         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5194         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5195         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5196         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5197         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5198         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5199         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5200         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5201 #endif
5202
5203
5204
5205 #if 0
5206         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5207         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5208         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5209         r_refdef.view.frustum[0].dist = m[15] - m[12];
5210
5211         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5212         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5213         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5214         r_refdef.view.frustum[1].dist = m[15] + m[12];
5215
5216         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5217         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5218         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5219         r_refdef.view.frustum[2].dist = m[15] - m[13];
5220
5221         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5222         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5223         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5224         r_refdef.view.frustum[3].dist = m[15] + m[13];
5225
5226         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5227         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5228         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5229         r_refdef.view.frustum[4].dist = m[15] - m[14];
5230
5231         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5232         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5233         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5234         r_refdef.view.frustum[5].dist = m[15] + m[14];
5235 #endif
5236
5237         if (r_refdef.view.useperspective)
5238         {
5239                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5240                 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]);
5241                 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]);
5242                 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]);
5243                 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]);
5244
5245                 // then the normals from the corners relative to origin
5246                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5247                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5248                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5249                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5250
5251                 // in a NORMAL view, forward cross left == up
5252                 // in a REFLECTED view, forward cross left == down
5253                 // so our cross products above need to be adjusted for a left handed coordinate system
5254                 CrossProduct(forward, left, v);
5255                 if(DotProduct(v, up) < 0)
5256                 {
5257                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5258                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5259                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5260                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5261                 }
5262
5263                 // Leaving those out was a mistake, those were in the old code, and they
5264                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5265                 // I couldn't reproduce it after adding those normalizations. --blub
5266                 VectorNormalize(r_refdef.view.frustum[0].normal);
5267                 VectorNormalize(r_refdef.view.frustum[1].normal);
5268                 VectorNormalize(r_refdef.view.frustum[2].normal);
5269                 VectorNormalize(r_refdef.view.frustum[3].normal);
5270
5271                 // make the corners absolute
5272                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5273                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5274                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5275                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5276
5277                 // one more normal
5278                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5279
5280                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5281                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5282                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5283                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5284                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5285         }
5286         else
5287         {
5288                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5289                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5290                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5291                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5292                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5293                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5294                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5295                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5296                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5297                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5298         }
5299         r_refdef.view.numfrustumplanes = 5;
5300
5301         if (r_refdef.view.useclipplane)
5302         {
5303                 r_refdef.view.numfrustumplanes = 6;
5304                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5305         }
5306
5307         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5308                 PlaneClassify(r_refdef.view.frustum + i);
5309
5310         // LordHavoc: note to all quake engine coders, Quake had a special case
5311         // for 90 degrees which assumed a square view (wrong), so I removed it,
5312         // Quake2 has it disabled as well.
5313
5314         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5315         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5316         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5317         //PlaneClassify(&frustum[0]);
5318
5319         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5320         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5321         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5322         //PlaneClassify(&frustum[1]);
5323
5324         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5325         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5326         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5327         //PlaneClassify(&frustum[2]);
5328
5329         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5330         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5331         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5332         //PlaneClassify(&frustum[3]);
5333
5334         // nearclip plane
5335         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5336         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5337         //PlaneClassify(&frustum[4]);
5338 }
5339
5340 void R_View_UpdateWithScissor(const int *myscissor)
5341 {
5342         R_Main_ResizeViewCache();
5343         R_View_SetFrustum(myscissor);
5344         R_View_WorldVisibility(r_refdef.view.useclipplane);
5345         R_View_UpdateEntityVisible();
5346         R_View_UpdateEntityLighting();
5347         R_AnimCache_CacheVisibleEntities();
5348 }
5349
5350 void R_View_Update(void)
5351 {
5352         R_Main_ResizeViewCache();
5353         R_View_SetFrustum(NULL);
5354         R_View_WorldVisibility(r_refdef.view.useclipplane);
5355         R_View_UpdateEntityVisible();
5356         R_View_UpdateEntityLighting();
5357         R_AnimCache_CacheVisibleEntities();
5358 }
5359
5360 float viewscalefpsadjusted = 1.0f;
5361
5362 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5363 {
5364         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5365         scale = bound(0.03125f, scale, 1.0f);
5366         *outwidth = (int)ceil(width * scale);
5367         *outheight = (int)ceil(height * scale);
5368 }
5369
5370 void R_Mesh_SetMainRenderTargets(void)
5371 {
5372         if (r_bloomstate.fbo_framebuffer)
5373                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5374         else
5375                 R_Mesh_ResetRenderTargets();
5376 }
5377
5378 void R_SetupView(qboolean allowwaterclippingplane)
5379 {
5380         const float *customclipplane = NULL;
5381         float plane[4];
5382         int scaledwidth, scaledheight;
5383         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5384         {
5385                 // LordHavoc: couldn't figure out how to make this approach the
5386                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5387                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5388                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5389                         dist = r_refdef.view.clipplane.dist;
5390                 plane[0] = r_refdef.view.clipplane.normal[0];
5391                 plane[1] = r_refdef.view.clipplane.normal[1];
5392                 plane[2] = r_refdef.view.clipplane.normal[2];
5393                 plane[3] = -dist;
5394                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5395         }
5396
5397         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5398         if (!r_refdef.view.useperspective)
5399                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5400         else if (vid.stencil && r_useinfinitefarclip.integer)
5401                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5402         else
5403                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5404         R_Mesh_SetMainRenderTargets();
5405         R_SetViewport(&r_refdef.view.viewport);
5406         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5407         {
5408                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5409                 float screenplane[4];
5410                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5411                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5412                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5413                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5414                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5415         }
5416 }
5417
5418 void R_EntityMatrix(const matrix4x4_t *matrix)
5419 {
5420         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5421         {
5422                 gl_modelmatrixchanged = false;
5423                 gl_modelmatrix = *matrix;
5424                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5425                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5426                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5427                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5428                 CHECKGLERROR
5429                 switch(vid.renderpath)
5430                 {
5431                 case RENDERPATH_D3D9:
5432 #ifdef SUPPORTD3D
5433                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5434                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5435 #endif
5436                         break;
5437                 case RENDERPATH_D3D10:
5438                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5439                         break;
5440                 case RENDERPATH_D3D11:
5441                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5442                         break;
5443                 case RENDERPATH_GL11:
5444                 case RENDERPATH_GL13:
5445                 case RENDERPATH_GLES1:
5446                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5447                         break;
5448                 case RENDERPATH_SOFT:
5449                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5450                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5451                         break;
5452                 case RENDERPATH_GL20:
5453                 case RENDERPATH_GLES2:
5454                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5455                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5456                         break;
5457                 }
5458         }
5459 }
5460
5461 void R_ResetViewRendering2D(void)
5462 {
5463         r_viewport_t viewport;
5464         DrawQ_Finish();
5465
5466         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5467         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);
5468         R_Mesh_ResetRenderTargets();
5469         R_SetViewport(&viewport);
5470         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5471         GL_Color(1, 1, 1, 1);
5472         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5473         GL_BlendFunc(GL_ONE, GL_ZERO);
5474         GL_ScissorTest(false);
5475         GL_DepthMask(false);
5476         GL_DepthRange(0, 1);
5477         GL_DepthTest(false);
5478         GL_DepthFunc(GL_LEQUAL);
5479         R_EntityMatrix(&identitymatrix);
5480         R_Mesh_ResetTextureState();
5481         GL_PolygonOffset(0, 0);
5482         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5483         switch(vid.renderpath)
5484         {
5485         case RENDERPATH_GL11:
5486         case RENDERPATH_GL13:
5487         case RENDERPATH_GL20:
5488         case RENDERPATH_GLES1:
5489         case RENDERPATH_GLES2:
5490                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5491                 break;
5492         case RENDERPATH_D3D9:
5493         case RENDERPATH_D3D10:
5494         case RENDERPATH_D3D11:
5495         case RENDERPATH_SOFT:
5496                 break;
5497         }
5498         GL_CullFace(GL_NONE);
5499 }
5500
5501 void R_ResetViewRendering3D(void)
5502 {
5503         DrawQ_Finish();
5504
5505         R_SetupView(true);
5506         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5507         GL_Color(1, 1, 1, 1);
5508         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5509         GL_BlendFunc(GL_ONE, GL_ZERO);
5510         GL_ScissorTest(true);
5511         GL_DepthMask(true);
5512         GL_DepthRange(0, 1);
5513         GL_DepthTest(true);
5514         GL_DepthFunc(GL_LEQUAL);
5515         R_EntityMatrix(&identitymatrix);
5516         R_Mesh_ResetTextureState();
5517         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5518         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5519         switch(vid.renderpath)
5520         {
5521         case RENDERPATH_GL11:
5522         case RENDERPATH_GL13:
5523         case RENDERPATH_GL20:
5524         case RENDERPATH_GLES1:
5525         case RENDERPATH_GLES2:
5526                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5527                 break;
5528         case RENDERPATH_D3D9:
5529         case RENDERPATH_D3D10:
5530         case RENDERPATH_D3D11:
5531         case RENDERPATH_SOFT:
5532                 break;
5533         }
5534         GL_CullFace(r_refdef.view.cullface_back);
5535 }
5536
5537 /*
5538 ================
5539 R_RenderView_UpdateViewVectors
5540 ================
5541 */
5542 static void R_RenderView_UpdateViewVectors(void)
5543 {
5544         // break apart the view matrix into vectors for various purposes
5545         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5546         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5547         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5548         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5549         // make an inverted copy of the view matrix for tracking sprites
5550         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5551 }
5552
5553 void R_RenderScene(void);
5554 void R_RenderWaterPlanes(void);
5555
5556 static void R_Water_StartFrame(void)
5557 {
5558         int i;
5559         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5560         r_waterstate_waterplane_t *p;
5561
5562         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5563                 return;
5564
5565         switch(vid.renderpath)
5566         {
5567         case RENDERPATH_GL20:
5568         case RENDERPATH_D3D9:
5569         case RENDERPATH_D3D10:
5570         case RENDERPATH_D3D11:
5571         case RENDERPATH_SOFT:
5572         case RENDERPATH_GLES2:
5573                 break;
5574         case RENDERPATH_GL11:
5575         case RENDERPATH_GL13:
5576         case RENDERPATH_GLES1:
5577                 return;
5578         }
5579
5580         // set waterwidth and waterheight to the water resolution that will be
5581         // used (often less than the screen resolution for faster rendering)
5582         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5583
5584         // calculate desired texture sizes
5585         // can't use water if the card does not support the texture size
5586         if (!r_water.integer || r_showsurfaces.integer)
5587                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5588         else if (vid.support.arb_texture_non_power_of_two)
5589         {
5590                 texturewidth = waterwidth;
5591                 textureheight = waterheight;
5592                 camerawidth = waterwidth;
5593                 cameraheight = waterheight;
5594         }
5595         else
5596         {
5597                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5598                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5599                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5600                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5601         }
5602
5603         // allocate textures as needed
5604         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5605         {
5606                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5607                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5608                 {
5609                         if (p->texture_refraction)
5610                                 R_FreeTexture(p->texture_refraction);
5611                         p->texture_refraction = NULL;
5612                         if (p->texture_reflection)
5613                                 R_FreeTexture(p->texture_reflection);
5614                         p->texture_reflection = NULL;
5615                         if (p->texture_camera)
5616                                 R_FreeTexture(p->texture_camera);
5617                         p->texture_camera = NULL;
5618                 }
5619                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5620                 r_waterstate.texturewidth = texturewidth;
5621                 r_waterstate.textureheight = textureheight;
5622                 r_waterstate.camerawidth = camerawidth;
5623                 r_waterstate.cameraheight = cameraheight;
5624         }
5625
5626         if (r_waterstate.texturewidth)
5627         {
5628                 int scaledwidth, scaledheight;
5629
5630                 r_waterstate.enabled = true;
5631
5632                 // when doing a reduced render (HDR) we want to use a smaller area
5633                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5634                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5635                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5636
5637                 // set up variables that will be used in shader setup
5638                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5639                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5640                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5641                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5642         }
5643
5644         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5645         r_waterstate.numwaterplanes = 0;
5646 }
5647
5648 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5649 {
5650         int planeindex, bestplaneindex, vertexindex;
5651         vec3_t mins, maxs, normal, center, v, n;
5652         vec_t planescore, bestplanescore;
5653         mplane_t plane;
5654         r_waterstate_waterplane_t *p;
5655         texture_t *t = R_GetCurrentTexture(surface->texture);
5656
5657         rsurface.texture = t;
5658         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5659         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5660         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5661                 return;
5662         // average the vertex normals, find the surface bounds (after deformvertexes)
5663         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5664         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5665         VectorCopy(n, normal);
5666         VectorCopy(v, mins);
5667         VectorCopy(v, maxs);
5668         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5669         {
5670                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5671                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5672                 VectorAdd(normal, n, normal);
5673                 mins[0] = min(mins[0], v[0]);
5674                 mins[1] = min(mins[1], v[1]);
5675                 mins[2] = min(mins[2], v[2]);
5676                 maxs[0] = max(maxs[0], v[0]);
5677                 maxs[1] = max(maxs[1], v[1]);
5678                 maxs[2] = max(maxs[2], v[2]);
5679         }
5680         VectorNormalize(normal);
5681         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5682
5683         VectorCopy(normal, plane.normal);
5684         VectorNormalize(plane.normal);
5685         plane.dist = DotProduct(center, plane.normal);
5686         PlaneClassify(&plane);
5687         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5688         {
5689                 // skip backfaces (except if nocullface is set)
5690 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5691 //                      return;
5692                 VectorNegate(plane.normal, plane.normal);
5693                 plane.dist *= -1;
5694                 PlaneClassify(&plane);
5695         }
5696
5697
5698         // find a matching plane if there is one
5699         bestplaneindex = -1;
5700         bestplanescore = 1048576.0f;
5701         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5702         {
5703                 if(p->camera_entity == t->camera_entity)
5704                 {
5705                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5706                         if (bestplaneindex < 0 || bestplanescore > planescore)
5707                         {
5708                                 bestplaneindex = planeindex;
5709                                 bestplanescore = planescore;
5710                         }
5711                 }
5712         }
5713         planeindex = bestplaneindex;
5714         p = r_waterstate.waterplanes + planeindex;
5715
5716         // if this surface does not fit any known plane rendered this frame, add one
5717         if ((planeindex < 0 || bestplanescore > 0.001f) && r_waterstate.numwaterplanes < r_waterstate.maxwaterplanes)
5718         {
5719                 // store the new plane
5720                 planeindex = r_waterstate.numwaterplanes++;
5721                 p = r_waterstate.waterplanes + planeindex;
5722                 p->plane = plane;
5723                 // clear materialflags and pvs
5724                 p->materialflags = 0;
5725                 p->pvsvalid = false;
5726                 p->camera_entity = t->camera_entity;
5727                 VectorCopy(mins, p->mins);
5728                 VectorCopy(maxs, p->maxs);
5729         }
5730         else
5731         {
5732                 // merge mins/maxs when we're adding this surface to the plane
5733                 p->mins[0] = min(p->mins[0], mins[0]);
5734                 p->mins[1] = min(p->mins[1], mins[1]);
5735                 p->mins[2] = min(p->mins[2], mins[2]);
5736                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5737                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5738                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5739         }
5740         // merge this surface's materialflags into the waterplane
5741         p->materialflags |= t->currentmaterialflags;
5742         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5743         {
5744                 // merge this surface's PVS into the waterplane
5745                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5746                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5747                 {
5748                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5749                         p->pvsvalid = true;
5750                 }
5751         }
5752 }
5753
5754 extern cvar_t r_drawparticles;
5755 extern cvar_t r_drawdecals;
5756
5757 static void R_Water_ProcessPlanes(void)
5758 {
5759         int myscissor[4];
5760         r_refdef_view_t originalview;
5761         r_refdef_view_t myview;
5762         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;
5763         r_waterstate_waterplane_t *p;
5764         vec3_t visorigin;
5765
5766         originalview = r_refdef.view;
5767
5768         // lowquality hack, temporarily shut down some cvars and restore afterwards
5769         qualityreduction = r_water_lowquality.integer;
5770         if (qualityreduction > 0)
5771         {
5772                 if (qualityreduction >= 1)
5773                 {
5774                         old_r_shadows = r_shadows.integer;
5775                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5776                         old_r_dlight = r_shadow_realtime_dlight.integer;
5777                         Cvar_SetValueQuick(&r_shadows, 0);
5778                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5779                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5780                 }
5781                 if (qualityreduction >= 2)
5782                 {
5783                         old_r_dynamic = r_dynamic.integer;
5784                         old_r_particles = r_drawparticles.integer;
5785                         old_r_decals = r_drawdecals.integer;
5786                         Cvar_SetValueQuick(&r_dynamic, 0);
5787                         Cvar_SetValueQuick(&r_drawparticles, 0);
5788                         Cvar_SetValueQuick(&r_drawdecals, 0);
5789                 }
5790         }
5791
5792         // make sure enough textures are allocated
5793         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5794         {
5795                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5796                 {
5797                         if (!p->texture_refraction)
5798                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5799                         if (!p->texture_refraction)
5800                                 goto error;
5801                 }
5802                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5803                 {
5804                         if (!p->texture_camera)
5805                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5806                         if (!p->texture_camera)
5807                                 goto error;
5808                 }
5809
5810                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5811                 {
5812                         if (!p->texture_reflection)
5813                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5814                         if (!p->texture_reflection)
5815                                 goto error;
5816                 }
5817         }
5818
5819         // render views
5820         r_refdef.view = originalview;
5821         r_refdef.view.showdebug = false;
5822         r_refdef.view.width = r_waterstate.waterwidth;
5823         r_refdef.view.height = r_waterstate.waterheight;
5824         r_refdef.view.useclipplane = true;
5825         myview = r_refdef.view;
5826         r_waterstate.renderingscene = true;
5827         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5828         {
5829                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5830                 {
5831                         r_refdef.view = myview;
5832                         if(r_water_scissormode.integer)
5833                         {
5834                                 R_SetupView(true);
5835                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5836                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5837                         }
5838
5839                         // render reflected scene and copy into texture
5840                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5841                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5842                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5843                         r_refdef.view.clipplane = p->plane;
5844                         // reverse the cullface settings for this render
5845                         r_refdef.view.cullface_front = GL_FRONT;
5846                         r_refdef.view.cullface_back = GL_BACK;
5847                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5848                         {
5849                                 r_refdef.view.usecustompvs = true;
5850                                 if (p->pvsvalid)
5851                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5852                                 else
5853                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5854                         }
5855
5856                         R_ResetViewRendering3D();
5857                         R_ClearScreen(r_refdef.fogenabled);
5858                         if(r_water_scissormode.integer & 2)
5859                                 R_View_UpdateWithScissor(myscissor);
5860                         else
5861                                 R_View_Update();
5862                         if(r_water_scissormode.integer & 1)
5863                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5864                         R_RenderScene();
5865
5866                         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);
5867                 }
5868
5869                 // render the normal view scene and copy into texture
5870                 // (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)
5871                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5872                 {
5873                         r_refdef.view = myview;
5874                         if(r_water_scissormode.integer)
5875                         {
5876                                 R_SetupView(true);
5877                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5878                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5879                         }
5880
5881                         r_waterstate.renderingrefraction = true;
5882
5883                         r_refdef.view.clipplane = p->plane;
5884                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5885                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5886
5887                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5888                         {
5889                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5890                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5891                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5892                                 R_RenderView_UpdateViewVectors();
5893                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5894                                 {
5895                                         r_refdef.view.usecustompvs = true;
5896                                         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);
5897                                 }
5898                         }
5899
5900                         PlaneClassify(&r_refdef.view.clipplane);
5901
5902                         R_ResetViewRendering3D();
5903                         R_ClearScreen(r_refdef.fogenabled);
5904                         if(r_water_scissormode.integer & 2)
5905                                 R_View_UpdateWithScissor(myscissor);
5906                         else
5907                                 R_View_Update();
5908                         if(r_water_scissormode.integer & 1)
5909                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5910                         R_RenderScene();
5911
5912                         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);
5913                         r_waterstate.renderingrefraction = false;
5914                 }
5915                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5916                 {
5917                         r_refdef.view = myview;
5918
5919                         r_refdef.view.clipplane = p->plane;
5920                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5921                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5922
5923                         r_refdef.view.width = r_waterstate.camerawidth;
5924                         r_refdef.view.height = r_waterstate.cameraheight;
5925                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5926                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5927                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5928                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5929
5930                         if(p->camera_entity)
5931                         {
5932                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5933                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5934                         }
5935
5936                         // note: all of the view is used for displaying... so
5937                         // there is no use in scissoring
5938
5939                         // reverse the cullface settings for this render
5940                         r_refdef.view.cullface_front = GL_FRONT;
5941                         r_refdef.view.cullface_back = GL_BACK;
5942                         // also reverse the view matrix
5943                         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
5944                         R_RenderView_UpdateViewVectors();
5945                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5946                         {
5947                                 r_refdef.view.usecustompvs = true;
5948                                 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);
5949                         }
5950                         
5951                         // camera needs no clipplane
5952                         r_refdef.view.useclipplane = false;
5953
5954                         PlaneClassify(&r_refdef.view.clipplane);
5955
5956                         R_ResetViewRendering3D();
5957                         R_ClearScreen(r_refdef.fogenabled);
5958                         R_View_Update();
5959                         R_RenderScene();
5960
5961                         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);
5962                         r_waterstate.renderingrefraction = false;
5963                 }
5964
5965         }
5966         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5967         r_waterstate.renderingscene = false;
5968         r_refdef.view = originalview;
5969         R_ResetViewRendering3D();
5970         R_ClearScreen(r_refdef.fogenabled);
5971         R_View_Update();
5972         goto finish;
5973 error:
5974         r_refdef.view = originalview;
5975         r_waterstate.renderingscene = false;
5976         Cvar_SetValueQuick(&r_water, 0);
5977         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5978 finish:
5979         // lowquality hack, restore cvars
5980         if (qualityreduction > 0)
5981         {
5982                 if (qualityreduction >= 1)
5983                 {
5984                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5985                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5986                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5987                 }
5988                 if (qualityreduction >= 2)
5989                 {
5990                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5991                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5992                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5993                 }
5994         }
5995 }
5996
5997 void R_Bloom_StartFrame(void)
5998 {
5999         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6000         int viewwidth, viewheight;
6001         textype_t textype;
6002
6003         if (r_viewscale_fpsscaling.integer)
6004         {
6005                 double actualframetime;
6006                 double targetframetime;
6007                 double adjust;
6008                 actualframetime = r_refdef.lastdrawscreentime;
6009                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6010                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6011                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6012                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6013                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6014                 viewscalefpsadjusted += adjust;
6015                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6016         }
6017         else
6018                 viewscalefpsadjusted = 1.0f;
6019
6020         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6021
6022         switch(vid.renderpath)
6023         {
6024         case RENDERPATH_GL20:
6025         case RENDERPATH_D3D9:
6026         case RENDERPATH_D3D10:
6027         case RENDERPATH_D3D11:
6028         case RENDERPATH_SOFT:
6029         case RENDERPATH_GLES2:
6030                 break;
6031         case RENDERPATH_GL11:
6032         case RENDERPATH_GL13:
6033         case RENDERPATH_GLES1:
6034                 return;
6035         }
6036
6037         // set bloomwidth and bloomheight to the bloom resolution that will be
6038         // used (often less than the screen resolution for faster rendering)
6039         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6040         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6041         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6042         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6043         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6044
6045         // calculate desired texture sizes
6046         if (vid.support.arb_texture_non_power_of_two)
6047         {
6048                 screentexturewidth = vid.width;
6049                 screentextureheight = vid.height;
6050                 bloomtexturewidth = r_bloomstate.bloomwidth;
6051                 bloomtextureheight = r_bloomstate.bloomheight;
6052         }
6053         else
6054         {
6055                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6056                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6057                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6058                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6059         }
6060
6061         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6062         {
6063                 Cvar_SetValueQuick(&r_hdr, 0);
6064                 Cvar_SetValueQuick(&r_bloom, 0);
6065                 Cvar_SetValueQuick(&r_motionblur, 0);
6066                 Cvar_SetValueQuick(&r_damageblur, 0);
6067         }
6068
6069         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
6070                 screentexturewidth = screentextureheight = 0;
6071         if (!r_hdr.integer && !r_bloom.integer)
6072                 bloomtexturewidth = bloomtextureheight = 0;
6073
6074         textype = TEXTYPE_COLORBUFFER;
6075         switch (vid.renderpath)
6076         {
6077         case RENDERPATH_GL20:
6078         case RENDERPATH_GLES2:
6079                 if (vid.support.ext_framebuffer_object)
6080                 {
6081                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6082                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6083                 }
6084                 break;
6085         case RENDERPATH_GL11:
6086         case RENDERPATH_GL13:
6087         case RENDERPATH_GLES1:
6088         case RENDERPATH_D3D9:
6089         case RENDERPATH_D3D10:
6090         case RENDERPATH_D3D11:
6091         case RENDERPATH_SOFT:
6092                 break;
6093         }
6094
6095         // allocate textures as needed
6096         if (r_bloomstate.screentexturewidth != screentexturewidth
6097          || r_bloomstate.screentextureheight != screentextureheight
6098          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6099          || r_bloomstate.bloomtextureheight != bloomtextureheight
6100          || r_bloomstate.texturetype != textype
6101          || r_bloomstate.viewfbo != r_viewfbo.integer)
6102         {
6103                 if (r_bloomstate.texture_bloom)
6104                         R_FreeTexture(r_bloomstate.texture_bloom);
6105                 r_bloomstate.texture_bloom = NULL;
6106                 if (r_bloomstate.texture_screen)
6107                         R_FreeTexture(r_bloomstate.texture_screen);
6108                 r_bloomstate.texture_screen = NULL;
6109                 if (r_bloomstate.fbo_framebuffer)
6110                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6111                 r_bloomstate.fbo_framebuffer = 0;
6112                 if (r_bloomstate.texture_framebuffercolor)
6113                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6114                 r_bloomstate.texture_framebuffercolor = NULL;
6115                 if (r_bloomstate.texture_framebufferdepth)
6116                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6117                 r_bloomstate.texture_framebufferdepth = NULL;
6118                 r_bloomstate.screentexturewidth = screentexturewidth;
6119                 r_bloomstate.screentextureheight = screentextureheight;
6120                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6121                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6122                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6123                 {
6124                         // FIXME: choose depth bits based on a cvar
6125                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6126                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6127                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6128                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6129 #ifndef USE_GLES2
6130                         // render depth into one texture and normalmap into the other
6131                         if (qglDrawBuffer)
6132                         {
6133                                 int status;
6134                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6135                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6136                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6137                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6138                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6139                         }
6140 #endif
6141                 }
6142                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6143                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6144                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6145                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6146                 r_bloomstate.viewfbo = r_viewfbo.integer;
6147                 r_bloomstate.texturetype = textype;
6148         }
6149
6150         // when doing a reduced render (HDR) we want to use a smaller area
6151         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6152         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6153         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6154         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6155         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6156
6157         // set up a texcoord array for the full resolution screen image
6158         // (we have to keep this around to copy back during final render)
6159         r_bloomstate.screentexcoord2f[0] = 0;
6160         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6161         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6162         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6163         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6164         r_bloomstate.screentexcoord2f[5] = 0;
6165         r_bloomstate.screentexcoord2f[6] = 0;
6166         r_bloomstate.screentexcoord2f[7] = 0;
6167
6168         // set up a texcoord array for the reduced resolution bloom image
6169         // (which will be additive blended over the screen image)
6170         r_bloomstate.bloomtexcoord2f[0] = 0;
6171         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6172         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6173         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6174         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6175         r_bloomstate.bloomtexcoord2f[5] = 0;
6176         r_bloomstate.bloomtexcoord2f[6] = 0;
6177         r_bloomstate.bloomtexcoord2f[7] = 0;
6178
6179         switch(vid.renderpath)
6180         {
6181         case RENDERPATH_GL11:
6182         case RENDERPATH_GL13:
6183         case RENDERPATH_GL20:
6184         case RENDERPATH_SOFT:
6185         case RENDERPATH_GLES1:
6186         case RENDERPATH_GLES2:
6187                 break;
6188         case RENDERPATH_D3D9:
6189         case RENDERPATH_D3D10:
6190         case RENDERPATH_D3D11:
6191                 {
6192                         int i;
6193                         for (i = 0;i < 4;i++)
6194                         {
6195                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6196                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6197                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6198                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6199                         }
6200                 }
6201                 break;
6202         }
6203
6204         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6205         {
6206                 r_bloomstate.enabled = true;
6207                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6208         }
6209
6210         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6211
6212         if (r_bloomstate.fbo_framebuffer)
6213                 r_refdef.view.clear = true;
6214 }
6215
6216 void R_Bloom_CopyBloomTexture(float colorscale)
6217 {
6218         r_refdef.stats.bloom++;
6219
6220         // scale down screen texture to the bloom texture size
6221         CHECKGLERROR
6222         R_Mesh_SetMainRenderTargets();
6223         R_SetViewport(&r_bloomstate.viewport);
6224         GL_BlendFunc(GL_ONE, GL_ZERO);
6225         GL_Color(colorscale, colorscale, colorscale, 1);
6226         // 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...
6227         switch(vid.renderpath)
6228         {
6229         case RENDERPATH_GL11:
6230         case RENDERPATH_GL13:
6231         case RENDERPATH_GL20:
6232         case RENDERPATH_GLES1:
6233         case RENDERPATH_GLES2:
6234         case RENDERPATH_SOFT:
6235                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6236                 break;
6237         case RENDERPATH_D3D9:
6238         case RENDERPATH_D3D10:
6239         case RENDERPATH_D3D11:
6240                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6241                 break;
6242         }
6243         // TODO: do boxfilter scale-down in shader?
6244         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6245         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6246         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6247
6248         // we now have a bloom image in the framebuffer
6249         // copy it into the bloom image texture for later processing
6250         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6251         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6252 }
6253
6254 void R_Bloom_CopyHDRTexture(void)
6255 {
6256         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6257         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6258 }
6259
6260 void R_Bloom_MakeTexture(void)
6261 {
6262         int x, range, dir;
6263         float xoffset, yoffset, r, brighten;
6264
6265         r_refdef.stats.bloom++;
6266
6267         R_ResetViewRendering2D();
6268
6269         // we have a bloom image in the framebuffer
6270         CHECKGLERROR
6271         R_SetViewport(&r_bloomstate.viewport);
6272
6273         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6274         {
6275                 x *= 2;
6276                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6277                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6278                 GL_Color(r,r,r,1);
6279                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6280                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6281                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6282                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6283
6284                 // copy the vertically blurred bloom view to a texture
6285                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6286                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6287         }
6288
6289         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6290         brighten = r_bloom_brighten.value;
6291         if (r_bloomstate.hdr)
6292                 brighten *= r_hdr_range.value;
6293         brighten = sqrt(brighten);
6294         if(range >= 1)
6295                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6296         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6297
6298         for (dir = 0;dir < 2;dir++)
6299         {
6300                 // blend on at multiple vertical offsets to achieve a vertical blur
6301                 // TODO: do offset blends using GLSL
6302                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6303                 GL_BlendFunc(GL_ONE, GL_ZERO);
6304                 for (x = -range;x <= range;x++)
6305                 {
6306                         if (!dir){xoffset = 0;yoffset = x;}
6307                         else {xoffset = x;yoffset = 0;}
6308                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6309                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6310                         // compute a texcoord array with the specified x and y offset
6311                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6312                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6313                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6314                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6315                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6316                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6317                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6318                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6319                         // this r value looks like a 'dot' particle, fading sharply to
6320                         // black at the edges
6321                         // (probably not realistic but looks good enough)
6322                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6323                         //r = brighten/(range*2+1);
6324                         r = brighten / (range * 2 + 1);
6325                         if(range >= 1)
6326                                 r *= (1 - x*x/(float)(range*range));
6327                         GL_Color(r, r, r, 1);
6328                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6329                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6330                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6331                         GL_BlendFunc(GL_ONE, GL_ONE);
6332                 }
6333
6334                 // copy the vertically blurred bloom view to a texture
6335                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6336                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6337         }
6338 }
6339
6340 void R_HDR_RenderBloomTexture(void)
6341 {
6342         int oldwidth, oldheight;
6343         float oldcolorscale;
6344         qboolean oldwaterstate;
6345
6346         oldwaterstate = r_waterstate.enabled;
6347         oldcolorscale = r_refdef.view.colorscale;
6348         oldwidth = r_refdef.view.width;
6349         oldheight = r_refdef.view.height;
6350         r_refdef.view.width = r_bloomstate.bloomwidth;
6351         r_refdef.view.height = r_bloomstate.bloomheight;
6352
6353         if(r_hdr.integer < 2)
6354                 r_waterstate.enabled = false;
6355
6356         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6357         // TODO: add exposure compensation features
6358         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6359
6360         r_refdef.view.showdebug = false;
6361         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6362
6363         R_ResetViewRendering3D();
6364
6365         R_ClearScreen(r_refdef.fogenabled);
6366         if (r_timereport_active)
6367                 R_TimeReport("HDRclear");
6368
6369         R_View_Update();
6370         if (r_timereport_active)
6371                 R_TimeReport("visibility");
6372
6373         // only do secondary renders with HDR if r_hdr is 2 or higher
6374         r_waterstate.numwaterplanes = 0;
6375         if (r_waterstate.enabled)
6376                 R_RenderWaterPlanes();
6377
6378         r_refdef.view.showdebug = true;
6379         R_RenderScene();
6380         r_waterstate.numwaterplanes = 0;
6381
6382         R_ResetViewRendering2D();
6383
6384         R_Bloom_CopyHDRTexture();
6385         R_Bloom_MakeTexture();
6386
6387         // restore the view settings
6388         r_waterstate.enabled = oldwaterstate;
6389         r_refdef.view.width = oldwidth;
6390         r_refdef.view.height = oldheight;
6391         r_refdef.view.colorscale = oldcolorscale;
6392
6393         R_ResetViewRendering3D();
6394
6395         R_ClearScreen(r_refdef.fogenabled);
6396         if (r_timereport_active)
6397                 R_TimeReport("viewclear");
6398 }
6399
6400 static void R_BlendView(void)
6401 {
6402         unsigned int permutation;
6403         float uservecs[4][4];
6404
6405         switch (vid.renderpath)
6406         {
6407         case RENDERPATH_GL20:
6408         case RENDERPATH_D3D9:
6409         case RENDERPATH_D3D10:
6410         case RENDERPATH_D3D11:
6411         case RENDERPATH_SOFT:
6412         case RENDERPATH_GLES2:
6413                 permutation =
6414                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6415                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6416                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6417                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6418                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6419
6420                 if (r_bloomstate.texture_screen)
6421                 {
6422                         // make sure the buffer is available
6423                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6424
6425                         R_ResetViewRendering2D();
6426                         R_Mesh_SetMainRenderTargets();
6427
6428                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6429                         {
6430                                 // declare variables
6431                                 float blur_factor, blur_mouseaccel, blur_velocity;
6432                                 static float blur_average; 
6433                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6434
6435                                 // set a goal for the factoring
6436                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6437                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6438                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6439                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6440                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6441                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6442
6443                                 // from the goal, pick an averaged value between goal and last value
6444                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6445                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6446                                 
6447                                 // enforce minimum amount of blur 
6448                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6449                                 
6450                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6451
6452                                 // calculate values into a standard alpha
6453                                 cl.motionbluralpha = 1 - exp(-
6454                                                 (
6455                                                  (r_motionblur.value * blur_factor / 80)
6456                                                  +
6457                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6458                                                 )
6459                                                 /
6460                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6461                                           );
6462                                 
6463                                 // randomization for the blur value to combat persistent ghosting
6464                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6465                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6466                                 
6467                                 // apply the blur
6468                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6469                                 {
6470                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6471                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6472                                         switch(vid.renderpath)
6473                                         {
6474                                         case RENDERPATH_GL11:
6475                                         case RENDERPATH_GL13:
6476                                         case RENDERPATH_GL20:
6477                                         case RENDERPATH_GLES1:
6478                                         case RENDERPATH_GLES2:
6479                                         case RENDERPATH_SOFT:
6480                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6481                                                 break;
6482                                         case RENDERPATH_D3D9:
6483                                         case RENDERPATH_D3D10:
6484                                         case RENDERPATH_D3D11:
6485                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6486                                                 break;
6487                                         }
6488                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6489                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6490                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6491                                 }
6492                                 
6493                                 // updates old view angles for next pass 
6494                                 VectorCopy(cl.viewangles, blur_oldangles);
6495                         }
6496
6497                         // copy view into the screen texture
6498                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6499                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6500                 }
6501                 else if (!r_bloomstate.texture_bloom)
6502                 {
6503                         // we may still have to do view tint...
6504                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6505                         {
6506                                 // apply a color tint to the whole view
6507                                 R_ResetViewRendering2D();
6508                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6509                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6510                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6511                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6512                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6513                         }
6514                         break; // no screen processing, no bloom, skip it
6515                 }
6516
6517                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6518                 {
6519                         // render simple bloom effect
6520                         // copy the screen and shrink it and darken it for the bloom process
6521                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6522                         // make the bloom texture
6523                         R_Bloom_MakeTexture();
6524                 }
6525
6526 #if _MSC_VER >= 1400
6527 #define sscanf sscanf_s
6528 #endif
6529                 memset(uservecs, 0, sizeof(uservecs));
6530                 if (r_glsl_postprocess_uservec1_enable.integer)
6531                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6532                 if (r_glsl_postprocess_uservec2_enable.integer)
6533                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6534                 if (r_glsl_postprocess_uservec3_enable.integer)
6535                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6536                 if (r_glsl_postprocess_uservec4_enable.integer)
6537                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6538
6539                 R_ResetViewRendering2D();
6540                 GL_Color(1, 1, 1, 1);
6541                 GL_BlendFunc(GL_ONE, GL_ZERO);
6542
6543                 switch(vid.renderpath)
6544                 {
6545                 case RENDERPATH_GL20:
6546                 case RENDERPATH_GLES2:
6547                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6548                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6549                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6550                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6551                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6552                         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]);
6553                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6554                         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]);
6555                         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]);
6556                         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]);
6557                         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]);
6558                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6559                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6560                         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);
6561                         break;
6562                 case RENDERPATH_D3D9:
6563 #ifdef SUPPORTD3D
6564                         // 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...
6565                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6566                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6567                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6568                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6569                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6570                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6571                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6572                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6573                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6574                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6575                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6576                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6577                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6578                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6579 #endif
6580                         break;
6581                 case RENDERPATH_D3D10:
6582                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6583                         break;
6584                 case RENDERPATH_D3D11:
6585                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6586                         break;
6587                 case RENDERPATH_SOFT:
6588                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6589                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6590                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6591                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6592                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6593                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6594                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6595                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6596                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6597                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6598                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6599                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6600                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6601                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6602                         break;
6603                 default:
6604                         break;
6605                 }
6606                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6607                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6608                 break;
6609         case RENDERPATH_GL11:
6610         case RENDERPATH_GL13:
6611         case RENDERPATH_GLES1:
6612                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6613                 {
6614                         // apply a color tint to the whole view
6615                         R_ResetViewRendering2D();
6616                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6617                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6618                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6619                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6620                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6621                 }
6622                 break;
6623         }
6624 }
6625
6626 matrix4x4_t r_waterscrollmatrix;
6627
6628 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6629 {
6630         // Nehahra fog
6631         if (gamemode == GAME_NEHAHRA)
6632         {
6633                 if (gl_fogenable.integer)
6634                 {
6635                         r_refdef.oldgl_fogenable = true;
6636                         r_refdef.fog_density = gl_fogdensity.value;
6637                         r_refdef.fog_red = gl_fogred.value;
6638                         r_refdef.fog_green = gl_foggreen.value;
6639                         r_refdef.fog_blue = gl_fogblue.value;
6640                         r_refdef.fog_alpha = 1;
6641                         r_refdef.fog_start = 0;
6642                         r_refdef.fog_end = gl_skyclip.value;
6643                         r_refdef.fog_height = 1<<30;
6644                         r_refdef.fog_fadedepth = 128;
6645                 }
6646                 else if (r_refdef.oldgl_fogenable)
6647                 {
6648                         r_refdef.oldgl_fogenable = false;
6649                         r_refdef.fog_density = 0;
6650                         r_refdef.fog_red = 0;
6651                         r_refdef.fog_green = 0;
6652                         r_refdef.fog_blue = 0;
6653                         r_refdef.fog_alpha = 0;
6654                         r_refdef.fog_start = 0;
6655                         r_refdef.fog_end = 0;
6656                         r_refdef.fog_height = 1<<30;
6657                         r_refdef.fog_fadedepth = 128;
6658                 }
6659         }
6660
6661         // fog parms
6662         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6663         r_refdef.fog_start = max(0, r_refdef.fog_start);
6664         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6665
6666         if (r_refdef.fog_density && r_drawfog.integer)
6667         {
6668                 r_refdef.fogenabled = true;
6669                 // this is the point where the fog reaches 0.9986 alpha, which we
6670                 // consider a good enough cutoff point for the texture
6671                 // (0.9986 * 256 == 255.6)
6672                 if (r_fog_exp2.integer)
6673                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6674                 else
6675                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6676                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6677                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6678                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6679                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6680                         R_BuildFogHeightTexture();
6681                 // fog color was already set
6682                 // update the fog texture
6683                 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)
6684                         R_BuildFogTexture();
6685                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6686                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6687         }
6688         else
6689                 r_refdef.fogenabled = false;
6690
6691         // fog color
6692         if (r_refdef.fog_density)
6693         {
6694                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6695                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6696                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6697
6698                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6699                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6700                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6701                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6702
6703                 {
6704                         vec3_t fogvec;
6705                         VectorCopy(r_refdef.fogcolor, fogvec);
6706                         //   color.rgb *= ContrastBoost * SceneBrightness;
6707                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6708                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6709                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6710                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6711                 }
6712         }
6713 }
6714
6715 void R_UpdateVariables(void)
6716 {
6717         R_Textures_Frame();
6718
6719         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6720
6721         r_refdef.farclip = r_farclip_base.value;
6722         if (r_refdef.scene.worldmodel)
6723                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6724         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6725
6726         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6727                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6728         r_refdef.polygonfactor = 0;
6729         r_refdef.polygonoffset = 0;
6730         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6731         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6732
6733         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6734         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6735         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6736         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6737         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6738         if (FAKELIGHT_ENABLED)
6739         {
6740                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6741         }
6742         if (r_showsurfaces.integer)
6743         {
6744                 r_refdef.scene.rtworld = false;
6745                 r_refdef.scene.rtworldshadows = false;
6746                 r_refdef.scene.rtdlight = false;
6747                 r_refdef.scene.rtdlightshadows = false;
6748                 r_refdef.lightmapintensity = 0;
6749         }
6750
6751         switch(vid.renderpath)
6752         {
6753         case RENDERPATH_GL20:
6754         case RENDERPATH_D3D9:
6755         case RENDERPATH_D3D10:
6756         case RENDERPATH_D3D11:
6757         case RENDERPATH_SOFT:
6758         case RENDERPATH_GLES2:
6759                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6760                 {
6761                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6762                         {
6763                                 // build GLSL gamma texture
6764 #define RAMPWIDTH 256
6765                                 unsigned short ramp[RAMPWIDTH * 3];
6766                                 unsigned char rampbgr[RAMPWIDTH][4];
6767                                 int i;
6768
6769                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6770
6771                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6772                                 for(i = 0; i < RAMPWIDTH; ++i)
6773                                 {
6774                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6775                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6776                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6777                                         rampbgr[i][3] = 0;
6778                                 }
6779                                 if (r_texture_gammaramps)
6780                                 {
6781                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6782                                 }
6783                                 else
6784                                 {
6785                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6786                                 }
6787                         }
6788                 }
6789                 else
6790                 {
6791                         // remove GLSL gamma texture
6792                 }
6793                 break;
6794         case RENDERPATH_GL11:
6795         case RENDERPATH_GL13:
6796         case RENDERPATH_GLES1:
6797                 break;
6798         }
6799 }
6800
6801 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6802 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6803 /*
6804 ================
6805 R_SelectScene
6806 ================
6807 */
6808 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6809         if( scenetype != r_currentscenetype ) {
6810                 // store the old scenetype
6811                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6812                 r_currentscenetype = scenetype;
6813                 // move in the new scene
6814                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6815         }
6816 }
6817
6818 /*
6819 ================
6820 R_GetScenePointer
6821 ================
6822 */
6823 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6824 {
6825         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6826         if( scenetype == r_currentscenetype ) {
6827                 return &r_refdef.scene;
6828         } else {
6829                 return &r_scenes_store[ scenetype ];
6830         }
6831 }
6832
6833 int R_SortEntities_Compare(const void *ap, const void *bp)
6834 {
6835         const entity_render_t *a = *(const entity_render_t **)ap;
6836         const entity_render_t *b = *(const entity_render_t **)bp;
6837
6838         // 1. compare model
6839         if(a->model < b->model)
6840                 return -1;
6841         if(a->model > b->model)
6842                 return +1;
6843
6844         // 2. compare skin
6845         // TODO possibly calculate the REAL skinnum here first using
6846         // skinscenes?
6847         if(a->skinnum < b->skinnum)
6848                 return -1;
6849         if(a->skinnum > b->skinnum)
6850                 return +1;
6851
6852         // everything we compared is equal
6853         return 0;
6854 }
6855 void R_SortEntities(void)
6856 {
6857         // below or equal 2 ents, sorting never gains anything
6858         if(r_refdef.scene.numentities <= 2)
6859                 return;
6860         // sort
6861         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6862 }
6863
6864 /*
6865 ================
6866 R_RenderView
6867 ================
6868 */
6869 int dpsoftrast_test;
6870 extern void R_Shadow_UpdateBounceGridTexture(void);
6871 extern cvar_t r_shadow_bouncegrid;
6872 void R_RenderView(void)
6873 {
6874         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6875
6876         dpsoftrast_test = r_test.integer;
6877
6878         if (r_timereport_active)
6879                 R_TimeReport("start");
6880         r_textureframe++; // used only by R_GetCurrentTexture
6881         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6882
6883         if(R_CompileShader_CheckStaticParms())
6884                 R_GLSL_Restart_f();
6885
6886         if (!r_drawentities.integer)
6887                 r_refdef.scene.numentities = 0;
6888         else if (r_sortentities.integer)
6889                 R_SortEntities();
6890
6891         R_AnimCache_ClearCache();
6892         R_FrameData_NewFrame();
6893
6894         /* adjust for stereo display */
6895         if(R_Stereo_Active())
6896         {
6897                 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);
6898                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6899         }
6900
6901         if (r_refdef.view.isoverlay)
6902         {
6903                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6904                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6905                 R_TimeReport("depthclear");
6906
6907                 r_refdef.view.showdebug = false;
6908
6909                 r_waterstate.enabled = false;
6910                 r_waterstate.numwaterplanes = 0;
6911
6912                 R_RenderScene();
6913
6914                 r_refdef.view.matrix = originalmatrix;
6915
6916                 CHECKGLERROR
6917                 return;
6918         }
6919
6920         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6921         {
6922                 r_refdef.view.matrix = originalmatrix;
6923                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6924         }
6925
6926         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6927
6928         R_RenderView_UpdateViewVectors();
6929
6930         R_Shadow_UpdateWorldLightSelection();
6931
6932         R_Bloom_StartFrame();
6933         R_Water_StartFrame();
6934
6935         CHECKGLERROR
6936         if (r_timereport_active)
6937                 R_TimeReport("viewsetup");
6938
6939         R_ResetViewRendering3D();
6940
6941         if (r_refdef.view.clear || r_refdef.fogenabled)
6942         {
6943                 R_ClearScreen(r_refdef.fogenabled);
6944                 if (r_timereport_active)
6945                         R_TimeReport("viewclear");
6946         }
6947         r_refdef.view.clear = true;
6948
6949         // this produces a bloom texture to be used in R_BlendView() later
6950         if (r_bloomstate.hdr)
6951         {
6952                 R_HDR_RenderBloomTexture();
6953                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6954                 r_textureframe++; // used only by R_GetCurrentTexture
6955         }
6956
6957         r_refdef.view.showdebug = true;
6958
6959         R_View_Update();
6960         if (r_timereport_active)
6961                 R_TimeReport("visibility");
6962
6963         R_Shadow_UpdateBounceGridTexture();
6964         if (r_timereport_active && r_shadow_bouncegrid.integer)
6965                 R_TimeReport("bouncegrid");
6966
6967         r_waterstate.numwaterplanes = 0;
6968         if (r_waterstate.enabled)
6969                 R_RenderWaterPlanes();
6970
6971         R_RenderScene();
6972         r_waterstate.numwaterplanes = 0;
6973
6974         R_BlendView();
6975         if (r_timereport_active)
6976                 R_TimeReport("blendview");
6977
6978         GL_Scissor(0, 0, vid.width, vid.height);
6979         GL_ScissorTest(false);
6980
6981         r_refdef.view.matrix = originalmatrix;
6982
6983         CHECKGLERROR
6984 }
6985
6986 void R_RenderWaterPlanes(void)
6987 {
6988         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6989         {
6990                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6991                 if (r_timereport_active)
6992                         R_TimeReport("waterworld");
6993         }
6994
6995         // don't let sound skip if going slow
6996         if (r_refdef.scene.extraupdate)
6997                 S_ExtraUpdate ();
6998
6999         R_DrawModelsAddWaterPlanes();
7000         if (r_timereport_active)
7001                 R_TimeReport("watermodels");
7002
7003         if (r_waterstate.numwaterplanes)
7004         {
7005                 R_Water_ProcessPlanes();
7006                 if (r_timereport_active)
7007                         R_TimeReport("waterscenes");
7008         }
7009 }
7010
7011 extern void R_DrawLightningBeams (void);
7012 extern void VM_CL_AddPolygonsToMeshQueue (void);
7013 extern void R_DrawPortals (void);
7014 extern cvar_t cl_locs_show;
7015 static void R_DrawLocs(void);
7016 static void R_DrawEntityBBoxes(void);
7017 static void R_DrawModelDecals(void);
7018 extern void R_DrawModelShadows(void);
7019 extern void R_DrawModelShadowMaps(void);
7020 extern cvar_t cl_decals_newsystem;
7021 extern qboolean r_shadow_usingdeferredprepass;
7022 void R_RenderScene(void)
7023 {
7024         qboolean shadowmapping = false;
7025
7026         if (r_timereport_active)
7027                 R_TimeReport("beginscene");
7028
7029         r_refdef.stats.renders++;
7030
7031         R_UpdateFog();
7032
7033         // don't let sound skip if going slow
7034         if (r_refdef.scene.extraupdate)
7035                 S_ExtraUpdate ();
7036
7037         R_MeshQueue_BeginScene();
7038
7039         R_SkyStartFrame();
7040
7041         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);
7042
7043         if (r_timereport_active)
7044                 R_TimeReport("skystartframe");
7045
7046         if (cl.csqc_vidvars.drawworld)
7047         {
7048                 // don't let sound skip if going slow
7049                 if (r_refdef.scene.extraupdate)
7050                         S_ExtraUpdate ();
7051
7052                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7053                 {
7054                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7055                         if (r_timereport_active)
7056                                 R_TimeReport("worldsky");
7057                 }
7058
7059                 if (R_DrawBrushModelsSky() && r_timereport_active)
7060                         R_TimeReport("bmodelsky");
7061
7062                 if (skyrendermasked && skyrenderlater)
7063                 {
7064                         // we have to force off the water clipping plane while rendering sky
7065                         R_SetupView(false);
7066                         R_Sky();
7067                         R_SetupView(true);
7068                         if (r_timereport_active)
7069                                 R_TimeReport("sky");
7070                 }
7071         }
7072
7073         R_Shadow_PrepareLights();
7074         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7075                 R_Shadow_PrepareModelShadows();
7076         if (r_timereport_active)
7077                 R_TimeReport("preparelights");
7078
7079         if (R_Shadow_ShadowMappingEnabled())
7080                 shadowmapping = true;
7081
7082         if (r_shadow_usingdeferredprepass)
7083                 R_Shadow_DrawPrepass();
7084
7085         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7086         {
7087                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7088                 if (r_timereport_active)
7089                         R_TimeReport("worlddepth");
7090         }
7091         if (r_depthfirst.integer >= 2)
7092         {
7093                 R_DrawModelsDepth();
7094                 if (r_timereport_active)
7095                         R_TimeReport("modeldepth");
7096         }
7097
7098         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7099         {
7100                 R_DrawModelShadowMaps();
7101                 R_ResetViewRendering3D();
7102                 // don't let sound skip if going slow
7103                 if (r_refdef.scene.extraupdate)
7104                         S_ExtraUpdate ();
7105         }
7106
7107         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7108         {
7109                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7110                 if (r_timereport_active)
7111                         R_TimeReport("world");
7112         }
7113
7114         // don't let sound skip if going slow
7115         if (r_refdef.scene.extraupdate)
7116                 S_ExtraUpdate ();
7117
7118         R_DrawModels();
7119         if (r_timereport_active)
7120                 R_TimeReport("models");
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_DrawModelShadows();
7129                 R_ResetViewRendering3D();
7130                 // don't let sound skip if going slow
7131                 if (r_refdef.scene.extraupdate)
7132                         S_ExtraUpdate ();
7133         }
7134
7135         if (!r_shadow_usingdeferredprepass)
7136         {
7137                 R_Shadow_DrawLights();
7138                 if (r_timereport_active)
7139                         R_TimeReport("rtlights");
7140         }
7141
7142         // don't let sound skip if going slow
7143         if (r_refdef.scene.extraupdate)
7144                 S_ExtraUpdate ();
7145
7146         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7147         {
7148                 R_DrawModelShadows();
7149                 R_ResetViewRendering3D();
7150                 // don't let sound skip if going slow
7151                 if (r_refdef.scene.extraupdate)
7152                         S_ExtraUpdate ();
7153         }
7154
7155         if (cl.csqc_vidvars.drawworld)
7156         {
7157                 if (cl_decals_newsystem.integer)
7158                 {
7159                         R_DrawModelDecals();
7160                         if (r_timereport_active)
7161                                 R_TimeReport("modeldecals");
7162                 }
7163                 else
7164                 {
7165                         R_DrawDecals();
7166                         if (r_timereport_active)
7167                                 R_TimeReport("decals");
7168                 }
7169
7170                 R_DrawParticles();
7171                 if (r_timereport_active)
7172                         R_TimeReport("particles");
7173
7174                 R_DrawExplosions();
7175                 if (r_timereport_active)
7176                         R_TimeReport("explosions");
7177
7178                 R_DrawLightningBeams();
7179                 if (r_timereport_active)
7180                         R_TimeReport("lightning");
7181         }
7182
7183         VM_CL_AddPolygonsToMeshQueue();
7184
7185         if (r_refdef.view.showdebug)
7186         {
7187                 if (cl_locs_show.integer)
7188                 {
7189                         R_DrawLocs();
7190                         if (r_timereport_active)
7191                                 R_TimeReport("showlocs");
7192                 }
7193
7194                 if (r_drawportals.integer)
7195                 {
7196                         R_DrawPortals();
7197                         if (r_timereport_active)
7198                                 R_TimeReport("portals");
7199                 }
7200
7201                 if (r_showbboxes.value > 0)
7202                 {
7203                         R_DrawEntityBBoxes();
7204                         if (r_timereport_active)
7205                                 R_TimeReport("bboxes");
7206                 }
7207         }
7208
7209         if (r_transparent.integer)
7210         {
7211                 R_MeshQueue_RenderTransparent();
7212                 if (r_timereport_active)
7213                         R_TimeReport("drawtrans");
7214         }
7215
7216         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))
7217         {
7218                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7219                 if (r_timereport_active)
7220                         R_TimeReport("worlddebug");
7221                 R_DrawModelsDebug();
7222                 if (r_timereport_active)
7223                         R_TimeReport("modeldebug");
7224         }
7225
7226         if (cl.csqc_vidvars.drawworld)
7227         {
7228                 R_Shadow_DrawCoronas();
7229                 if (r_timereport_active)
7230                         R_TimeReport("coronas");
7231         }
7232
7233 #if 0
7234         {
7235                 GL_DepthTest(false);
7236                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7237                 GL_Color(1, 1, 1, 1);
7238                 qglBegin(GL_POLYGON);
7239                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7240                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7241                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7242                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7243                 qglEnd();
7244                 qglBegin(GL_POLYGON);
7245                 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]);
7246                 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]);
7247                 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]);
7248                 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]);
7249                 qglEnd();
7250                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7251         }
7252 #endif
7253
7254         // don't let sound skip if going slow
7255         if (r_refdef.scene.extraupdate)
7256                 S_ExtraUpdate ();
7257
7258         R_ResetViewRendering2D();
7259 }
7260
7261 static const unsigned short bboxelements[36] =
7262 {
7263         5, 1, 3, 5, 3, 7,
7264         6, 2, 0, 6, 0, 4,
7265         7, 3, 2, 7, 2, 6,
7266         4, 0, 1, 4, 1, 5,
7267         4, 5, 7, 4, 7, 6,
7268         1, 0, 2, 1, 2, 3,
7269 };
7270
7271 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7272 {
7273         int i;
7274         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7275
7276         RSurf_ActiveWorldEntity();
7277
7278         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7279         GL_DepthMask(false);
7280         GL_DepthRange(0, 1);
7281         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7282 //      R_Mesh_ResetTextureState();
7283
7284         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7285         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7286         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7287         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7288         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7289         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7290         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7291         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7292         R_FillColors(color4f, 8, cr, cg, cb, ca);
7293         if (r_refdef.fogenabled)
7294         {
7295                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7296                 {
7297                         f1 = RSurf_FogVertex(v);
7298                         f2 = 1 - f1;
7299                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7300                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7301                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7302                 }
7303         }
7304         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7305         R_Mesh_ResetTextureState();
7306         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7307         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7308 }
7309
7310 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7311 {
7312         int i;
7313         float color[4];
7314         prvm_edict_t *edict;
7315         prvm_prog_t *prog_save = prog;
7316
7317         // this function draws bounding boxes of server entities
7318         if (!sv.active)
7319                 return;
7320
7321         GL_CullFace(GL_NONE);
7322         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7323
7324         prog = 0;
7325         SV_VM_Begin();
7326         for (i = 0;i < numsurfaces;i++)
7327         {
7328                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7329                 switch ((int)PRVM_serveredictfloat(edict, solid))
7330                 {
7331                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7332                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7333                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7334                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7335                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7336                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7337                 }
7338                 color[3] *= r_showbboxes.value;
7339                 color[3] = bound(0, color[3], 1);
7340                 GL_DepthTest(!r_showdisabledepthtest.integer);
7341                 GL_CullFace(r_refdef.view.cullface_front);
7342                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7343         }
7344         SV_VM_End();
7345         prog = prog_save;
7346 }
7347
7348 static void R_DrawEntityBBoxes(void)
7349 {
7350         int i;
7351         prvm_edict_t *edict;
7352         vec3_t center;
7353         prvm_prog_t *prog_save = prog;
7354
7355         // this function draws bounding boxes of server entities
7356         if (!sv.active)
7357                 return;
7358
7359         prog = 0;
7360         SV_VM_Begin();
7361         for (i = 0;i < prog->num_edicts;i++)
7362         {
7363                 edict = PRVM_EDICT_NUM(i);
7364                 if (edict->priv.server->free)
7365                         continue;
7366                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7367                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7368                         continue;
7369                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7370                         continue;
7371                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7372                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7373         }
7374         SV_VM_End();
7375         prog = prog_save;
7376 }
7377
7378 static const int nomodelelement3i[24] =
7379 {
7380         5, 2, 0,
7381         5, 1, 2,
7382         5, 0, 3,
7383         5, 3, 1,
7384         0, 2, 4,
7385         2, 1, 4,
7386         3, 0, 4,
7387         1, 3, 4
7388 };
7389
7390 static const unsigned short nomodelelement3s[24] =
7391 {
7392         5, 2, 0,
7393         5, 1, 2,
7394         5, 0, 3,
7395         5, 3, 1,
7396         0, 2, 4,
7397         2, 1, 4,
7398         3, 0, 4,
7399         1, 3, 4
7400 };
7401
7402 static const float nomodelvertex3f[6*3] =
7403 {
7404         -16,   0,   0,
7405          16,   0,   0,
7406           0, -16,   0,
7407           0,  16,   0,
7408           0,   0, -16,
7409           0,   0,  16
7410 };
7411
7412 static const float nomodelcolor4f[6*4] =
7413 {
7414         0.0f, 0.0f, 0.5f, 1.0f,
7415         0.0f, 0.0f, 0.5f, 1.0f,
7416         0.0f, 0.5f, 0.0f, 1.0f,
7417         0.0f, 0.5f, 0.0f, 1.0f,
7418         0.5f, 0.0f, 0.0f, 1.0f,
7419         0.5f, 0.0f, 0.0f, 1.0f
7420 };
7421
7422 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7423 {
7424         int i;
7425         float f1, f2, *c;
7426         float color4f[6*4];
7427
7428         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);
7429
7430         // this is only called once per entity so numsurfaces is always 1, and
7431         // surfacelist is always {0}, so this code does not handle batches
7432
7433         if (rsurface.ent_flags & RENDER_ADDITIVE)
7434         {
7435                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7436                 GL_DepthMask(false);
7437         }
7438         else if (rsurface.colormod[3] < 1)
7439         {
7440                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7441                 GL_DepthMask(false);
7442         }
7443         else
7444         {
7445                 GL_BlendFunc(GL_ONE, GL_ZERO);
7446                 GL_DepthMask(true);
7447         }
7448         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7449         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7450         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7451         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7452         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7453         for (i = 0, c = color4f;i < 6;i++, c += 4)
7454         {
7455                 c[0] *= rsurface.colormod[0];
7456                 c[1] *= rsurface.colormod[1];
7457                 c[2] *= rsurface.colormod[2];
7458                 c[3] *= rsurface.colormod[3];
7459         }
7460         if (r_refdef.fogenabled)
7461         {
7462                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7463                 {
7464                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7465                         f2 = 1 - f1;
7466                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7467                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7468                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7469                 }
7470         }
7471 //      R_Mesh_ResetTextureState();
7472         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7473         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7474         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7475 }
7476
7477 void R_DrawNoModel(entity_render_t *ent)
7478 {
7479         vec3_t org;
7480         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7481         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7482                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7483         else
7484                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7485 }
7486
7487 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7488 {
7489         vec3_t right1, right2, diff, normal;
7490
7491         VectorSubtract (org2, org1, normal);
7492
7493         // calculate 'right' vector for start
7494         VectorSubtract (r_refdef.view.origin, org1, diff);
7495         CrossProduct (normal, diff, right1);
7496         VectorNormalize (right1);
7497
7498         // calculate 'right' vector for end
7499         VectorSubtract (r_refdef.view.origin, org2, diff);
7500         CrossProduct (normal, diff, right2);
7501         VectorNormalize (right2);
7502
7503         vert[ 0] = org1[0] + width * right1[0];
7504         vert[ 1] = org1[1] + width * right1[1];
7505         vert[ 2] = org1[2] + width * right1[2];
7506         vert[ 3] = org1[0] - width * right1[0];
7507         vert[ 4] = org1[1] - width * right1[1];
7508         vert[ 5] = org1[2] - width * right1[2];
7509         vert[ 6] = org2[0] - width * right2[0];
7510         vert[ 7] = org2[1] - width * right2[1];
7511         vert[ 8] = org2[2] - width * right2[2];
7512         vert[ 9] = org2[0] + width * right2[0];
7513         vert[10] = org2[1] + width * right2[1];
7514         vert[11] = org2[2] + width * right2[2];
7515 }
7516
7517 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)
7518 {
7519         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7520         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7521         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7522         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7523         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7524         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7525         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7526         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7527         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7528         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7529         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7530         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7531 }
7532
7533 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7534 {
7535         int i;
7536         float *vertex3f;
7537         float v[3];
7538         VectorSet(v, x, y, z);
7539         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7540                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7541                         break;
7542         if (i == mesh->numvertices)
7543         {
7544                 if (mesh->numvertices < mesh->maxvertices)
7545                 {
7546                         VectorCopy(v, vertex3f);
7547                         mesh->numvertices++;
7548                 }
7549                 return mesh->numvertices;
7550         }
7551         else
7552                 return i;
7553 }
7554
7555 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7556 {
7557         int i;
7558         int *e, element[3];
7559         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7560         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7561         e = mesh->element3i + mesh->numtriangles * 3;
7562         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7563         {
7564                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[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 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7577 {
7578         int i;
7579         int *e, element[3];
7580         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7581         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7582         e = mesh->element3i + mesh->numtriangles * 3;
7583         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7584         {
7585                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7586                 if (mesh->numtriangles < mesh->maxtriangles)
7587                 {
7588                         *e++ = element[0];
7589                         *e++ = element[1];
7590                         *e++ = element[2];
7591                         mesh->numtriangles++;
7592                 }
7593                 element[1] = element[2];
7594         }
7595 }
7596
7597 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7598 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7599 {
7600         int planenum, planenum2;
7601         int w;
7602         int tempnumpoints;
7603         mplane_t *plane, *plane2;
7604         double maxdist;
7605         double temppoints[2][256*3];
7606         // figure out how large a bounding box we need to properly compute this brush
7607         maxdist = 0;
7608         for (w = 0;w < numplanes;w++)
7609                 maxdist = max(maxdist, fabs(planes[w].dist));
7610         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7611         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7612         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7613         {
7614                 w = 0;
7615                 tempnumpoints = 4;
7616                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7617                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7618                 {
7619                         if (planenum2 == planenum)
7620                                 continue;
7621                         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);
7622                         w = !w;
7623                 }
7624                 if (tempnumpoints < 3)
7625                         continue;
7626                 // generate elements forming a triangle fan for this polygon
7627                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7628         }
7629 }
7630
7631 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)
7632 {
7633         texturelayer_t *layer;
7634         layer = t->currentlayers + t->currentnumlayers++;
7635         layer->type = type;
7636         layer->depthmask = depthmask;
7637         layer->blendfunc1 = blendfunc1;
7638         layer->blendfunc2 = blendfunc2;
7639         layer->texture = texture;
7640         layer->texmatrix = *matrix;
7641         layer->color[0] = r;
7642         layer->color[1] = g;
7643         layer->color[2] = b;
7644         layer->color[3] = a;
7645 }
7646
7647 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7648 {
7649         if(parms[0] == 0 && parms[1] == 0)
7650                 return false;
7651         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7652                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7653                         return false;
7654         return true;
7655 }
7656
7657 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7658 {
7659         double index, f;
7660         index = parms[2] + rsurface.shadertime * parms[3];
7661         index -= floor(index);
7662         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7663         {
7664         default:
7665         case Q3WAVEFUNC_NONE:
7666         case Q3WAVEFUNC_NOISE:
7667         case Q3WAVEFUNC_COUNT:
7668                 f = 0;
7669                 break;
7670         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7671         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7672         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7673         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7674         case Q3WAVEFUNC_TRIANGLE:
7675                 index *= 4;
7676                 f = index - floor(index);
7677                 if (index < 1)
7678                 {
7679                         // f = f;
7680                 }
7681                 else if (index < 2)
7682                         f = 1 - f;
7683                 else if (index < 3)
7684                         f = -f;
7685                 else
7686                         f = -(1 - f);
7687                 break;
7688         }
7689         f = parms[0] + parms[1] * f;
7690         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7691                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7692         return (float) f;
7693 }
7694
7695 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7696 {
7697         int w, h, idx;
7698         double f;
7699         double offsetd[2];
7700         float tcmat[12];
7701         matrix4x4_t matrix, temp;
7702         switch(tcmod->tcmod)
7703         {
7704                 case Q3TCMOD_COUNT:
7705                 case Q3TCMOD_NONE:
7706                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7707                                 matrix = r_waterscrollmatrix;
7708                         else
7709                                 matrix = identitymatrix;
7710                         break;
7711                 case Q3TCMOD_ENTITYTRANSLATE:
7712                         // this is used in Q3 to allow the gamecode to control texcoord
7713                         // scrolling on the entity, which is not supported in darkplaces yet.
7714                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7715                         break;
7716                 case Q3TCMOD_ROTATE:
7717                         f = tcmod->parms[0] * rsurface.shadertime;
7718                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7719                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7720                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7721                         break;
7722                 case Q3TCMOD_SCALE:
7723                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7724                         break;
7725                 case Q3TCMOD_SCROLL:
7726                         // extra care is needed because of precision breakdown with large values of time
7727                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7728                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7729                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7730                         break;
7731                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7732                         w = (int) tcmod->parms[0];
7733                         h = (int) tcmod->parms[1];
7734                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7735                         f = f - floor(f);
7736                         idx = (int) floor(f * w * h);
7737                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7738                         break;
7739                 case Q3TCMOD_STRETCH:
7740                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7741                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7742                         break;
7743                 case Q3TCMOD_TRANSFORM:
7744                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7745                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7746                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7747                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7748                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7749                         break;
7750                 case Q3TCMOD_TURBULENT:
7751                         // this is handled in the RSurf_PrepareVertices function
7752                         matrix = identitymatrix;
7753                         break;
7754         }
7755         temp = *texmatrix;
7756         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7757 }
7758
7759 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7760 {
7761         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7762         char name[MAX_QPATH];
7763         skinframe_t *skinframe;
7764         unsigned char pixels[296*194];
7765         strlcpy(cache->name, skinname, sizeof(cache->name));
7766         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7767         if (developer_loading.integer)
7768                 Con_Printf("loading %s\n", name);
7769         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7770         if (!skinframe || !skinframe->base)
7771         {
7772                 unsigned char *f;
7773                 fs_offset_t filesize;
7774                 skinframe = NULL;
7775                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7776                 if (f)
7777                 {
7778                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7779                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7780                         Mem_Free(f);
7781                 }
7782         }
7783         cache->skinframe = skinframe;
7784 }
7785
7786 texture_t *R_GetCurrentTexture(texture_t *t)
7787 {
7788         int i;
7789         const entity_render_t *ent = rsurface.entity;
7790         dp_model_t *model = ent->model;
7791         q3shaderinfo_layer_tcmod_t *tcmod;
7792
7793         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7794                 return t->currentframe;
7795         t->update_lastrenderframe = r_textureframe;
7796         t->update_lastrenderentity = (void *)ent;
7797
7798         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7799                 t->camera_entity = ent->entitynumber;
7800         else
7801                 t->camera_entity = 0;
7802
7803         // switch to an alternate material if this is a q1bsp animated material
7804         {
7805                 texture_t *texture = t;
7806                 int s = rsurface.ent_skinnum;
7807                 if ((unsigned int)s >= (unsigned int)model->numskins)
7808                         s = 0;
7809                 if (model->skinscenes)
7810                 {
7811                         if (model->skinscenes[s].framecount > 1)
7812                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7813                         else
7814                                 s = model->skinscenes[s].firstframe;
7815                 }
7816                 if (s > 0)
7817                         t = t + s * model->num_surfaces;
7818                 if (t->animated)
7819                 {
7820                         // use an alternate animation if the entity's frame is not 0,
7821                         // and only if the texture has an alternate animation
7822                         if (rsurface.ent_alttextures && t->anim_total[1])
7823                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7824                         else
7825                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7826                 }
7827                 texture->currentframe = t;
7828         }
7829
7830         // update currentskinframe to be a qw skin or animation frame
7831         if (rsurface.ent_qwskin >= 0)
7832         {
7833                 i = rsurface.ent_qwskin;
7834                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7835                 {
7836                         r_qwskincache_size = cl.maxclients;
7837                         if (r_qwskincache)
7838                                 Mem_Free(r_qwskincache);
7839                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7840                 }
7841                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7842                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7843                 t->currentskinframe = r_qwskincache[i].skinframe;
7844                 if (t->currentskinframe == NULL)
7845                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7846         }
7847         else if (t->numskinframes >= 2)
7848                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7849         if (t->backgroundnumskinframes >= 2)
7850                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7851
7852         t->currentmaterialflags = t->basematerialflags;
7853         t->currentalpha = rsurface.colormod[3];
7854         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7855                 t->currentalpha *= r_wateralpha.value;
7856         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7857                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7858         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7859                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7860         if (!(rsurface.ent_flags & RENDER_LIGHT))
7861                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7862         else if (FAKELIGHT_ENABLED)
7863         {
7864                 // no modellight if using fakelight for the map
7865         }
7866         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7867         {
7868                 // pick a model lighting mode
7869                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7870                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7871                 else
7872                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7873         }
7874         if (rsurface.ent_flags & RENDER_ADDITIVE)
7875                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7876         else if (t->currentalpha < 1)
7877                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7878         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7879         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7880                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7881         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7882                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7883         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7884                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7885         if (t->backgroundnumskinframes)
7886                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7887         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7888         {
7889                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7890                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7891         }
7892         else
7893                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7894         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7895         {
7896                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7897                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7898         }
7899         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7900                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7901
7902         // there is no tcmod
7903         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7904         {
7905                 t->currenttexmatrix = r_waterscrollmatrix;
7906                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7907         }
7908         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7909         {
7910                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7911                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7912         }
7913
7914         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7915                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7916         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7917                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7918
7919         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7920         if (t->currentskinframe->qpixels)
7921                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7922         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7923         if (!t->basetexture)
7924                 t->basetexture = r_texture_notexture;
7925         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7926         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7927         t->nmaptexture = t->currentskinframe->nmap;
7928         if (!t->nmaptexture)
7929                 t->nmaptexture = r_texture_blanknormalmap;
7930         t->glosstexture = r_texture_black;
7931         t->glowtexture = t->currentskinframe->glow;
7932         t->fogtexture = t->currentskinframe->fog;
7933         t->reflectmasktexture = t->currentskinframe->reflect;
7934         if (t->backgroundnumskinframes)
7935         {
7936                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7937                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7938                 t->backgroundglosstexture = r_texture_black;
7939                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7940                 if (!t->backgroundnmaptexture)
7941                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7942         }
7943         else
7944         {
7945                 t->backgroundbasetexture = r_texture_white;
7946                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7947                 t->backgroundglosstexture = r_texture_black;
7948                 t->backgroundglowtexture = NULL;
7949         }
7950         t->specularpower = r_shadow_glossexponent.value;
7951         // TODO: store reference values for these in the texture?
7952         t->specularscale = 0;
7953         if (r_shadow_gloss.integer > 0)
7954         {
7955                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7956                 {
7957                         if (r_shadow_glossintensity.value > 0)
7958                         {
7959                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7960                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7961                                 t->specularscale = r_shadow_glossintensity.value;
7962                         }
7963                 }
7964                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7965                 {
7966                         t->glosstexture = r_texture_white;
7967                         t->backgroundglosstexture = r_texture_white;
7968                         t->specularscale = r_shadow_gloss2intensity.value;
7969                         t->specularpower = r_shadow_gloss2exponent.value;
7970                 }
7971         }
7972         t->specularscale *= t->specularscalemod;
7973         t->specularpower *= t->specularpowermod;
7974         t->rtlightambient = 0;
7975
7976         // lightmaps mode looks bad with dlights using actual texturing, so turn
7977         // off the colormap and glossmap, but leave the normalmap on as it still
7978         // accurately represents the shading involved
7979         if (gl_lightmaps.integer)
7980         {
7981                 t->basetexture = r_texture_grey128;
7982                 t->pantstexture = r_texture_black;
7983                 t->shirttexture = r_texture_black;
7984                 t->nmaptexture = r_texture_blanknormalmap;
7985                 t->glosstexture = r_texture_black;
7986                 t->glowtexture = NULL;
7987                 t->fogtexture = NULL;
7988                 t->reflectmasktexture = NULL;
7989                 t->backgroundbasetexture = NULL;
7990                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7991                 t->backgroundglosstexture = r_texture_black;
7992                 t->backgroundglowtexture = NULL;
7993                 t->specularscale = 0;
7994                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7995         }
7996
7997         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7998         VectorClear(t->dlightcolor);
7999         t->currentnumlayers = 0;
8000         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8001         {
8002                 int blendfunc1, blendfunc2;
8003                 qboolean depthmask;
8004                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8005                 {
8006                         blendfunc1 = GL_SRC_ALPHA;
8007                         blendfunc2 = GL_ONE;
8008                 }
8009                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8010                 {
8011                         blendfunc1 = GL_SRC_ALPHA;
8012                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8013                 }
8014                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8015                 {
8016                         blendfunc1 = t->customblendfunc[0];
8017                         blendfunc2 = t->customblendfunc[1];
8018                 }
8019                 else
8020                 {
8021                         blendfunc1 = GL_ONE;
8022                         blendfunc2 = GL_ZERO;
8023                 }
8024                 // don't colormod evilblend textures
8025                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8026                         VectorSet(t->lightmapcolor, 1, 1, 1);
8027                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8028                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8029                 {
8030                         // fullbright is not affected by r_refdef.lightmapintensity
8031                         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]);
8032                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8033                                 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]);
8034                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8035                                 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]);
8036                 }
8037                 else
8038                 {
8039                         vec3_t ambientcolor;
8040                         float colorscale;
8041                         // set the color tint used for lights affecting this surface
8042                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8043                         colorscale = 2;
8044                         // q3bsp has no lightmap updates, so the lightstylevalue that
8045                         // would normally be baked into the lightmap must be
8046                         // applied to the color
8047                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8048                         if (model->type == mod_brushq3)
8049                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8050                         colorscale *= r_refdef.lightmapintensity;
8051                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8052                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8053                         // basic lit geometry
8054                         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]);
8055                         // add pants/shirt if needed
8056                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8057                                 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]);
8058                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8059                                 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]);
8060                         // now add ambient passes if needed
8061                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8062                         {
8063                                 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]);
8064                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8065                                         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]);
8066                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8067                                         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]);
8068                         }
8069                 }
8070                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8071                         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]);
8072                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8073                 {
8074                         // if this is opaque use alpha blend which will darken the earlier
8075                         // passes cheaply.
8076                         //
8077                         // if this is an alpha blended material, all the earlier passes
8078                         // were darkened by fog already, so we only need to add the fog
8079                         // color ontop through the fog mask texture
8080                         //
8081                         // if this is an additive blended material, all the earlier passes
8082                         // were darkened by fog already, and we should not add fog color
8083                         // (because the background was not darkened, there is no fog color
8084                         // that was lost behind it).
8085                         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]);
8086                 }
8087         }
8088
8089         return t->currentframe;
8090 }
8091
8092 rsurfacestate_t rsurface;
8093
8094 void RSurf_ActiveWorldEntity(void)
8095 {
8096         dp_model_t *model = r_refdef.scene.worldmodel;
8097         //if (rsurface.entity == r_refdef.scene.worldentity)
8098         //      return;
8099         rsurface.entity = r_refdef.scene.worldentity;
8100         rsurface.skeleton = NULL;
8101         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8102         rsurface.ent_skinnum = 0;
8103         rsurface.ent_qwskin = -1;
8104         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8105         rsurface.shadertime = r_refdef.scene.time;
8106         rsurface.matrix = identitymatrix;
8107         rsurface.inversematrix = identitymatrix;
8108         rsurface.matrixscale = 1;
8109         rsurface.inversematrixscale = 1;
8110         R_EntityMatrix(&identitymatrix);
8111         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8112         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8113         rsurface.fograngerecip = r_refdef.fograngerecip;
8114         rsurface.fogheightfade = r_refdef.fogheightfade;
8115         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8116         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8117         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8118         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8119         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8120         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8121         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8122         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8123         rsurface.colormod[3] = 1;
8124         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);
8125         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8126         rsurface.frameblend[0].lerp = 1;
8127         rsurface.ent_alttextures = false;
8128         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8129         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8130         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8131         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8132         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8133         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8134         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8135         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8136         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8137         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8138         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8139         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8140         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8141         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8142         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8143         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8144         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8145         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8146         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8147         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8148         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8149         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8150         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8151         rsurface.modelelement3i = model->surfmesh.data_element3i;
8152         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8153         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8154         rsurface.modelelement3s = model->surfmesh.data_element3s;
8155         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8156         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8157         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8158         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8159         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8160         rsurface.modelsurfaces = model->data_surfaces;
8161         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8162         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8163         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8164         rsurface.modelgeneratedvertex = false;
8165         rsurface.batchgeneratedvertex = false;
8166         rsurface.batchfirstvertex = 0;
8167         rsurface.batchnumvertices = 0;
8168         rsurface.batchfirsttriangle = 0;
8169         rsurface.batchnumtriangles = 0;
8170         rsurface.batchvertex3f  = NULL;
8171         rsurface.batchvertex3f_vertexbuffer = NULL;
8172         rsurface.batchvertex3f_bufferoffset = 0;
8173         rsurface.batchsvector3f = NULL;
8174         rsurface.batchsvector3f_vertexbuffer = NULL;
8175         rsurface.batchsvector3f_bufferoffset = 0;
8176         rsurface.batchtvector3f = NULL;
8177         rsurface.batchtvector3f_vertexbuffer = NULL;
8178         rsurface.batchtvector3f_bufferoffset = 0;
8179         rsurface.batchnormal3f  = NULL;
8180         rsurface.batchnormal3f_vertexbuffer = NULL;
8181         rsurface.batchnormal3f_bufferoffset = 0;
8182         rsurface.batchlightmapcolor4f = NULL;
8183         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8184         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8185         rsurface.batchtexcoordtexture2f = NULL;
8186         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8187         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8188         rsurface.batchtexcoordlightmap2f = NULL;
8189         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8190         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8191         rsurface.batchvertexmesh = NULL;
8192         rsurface.batchvertexmeshbuffer = NULL;
8193         rsurface.batchvertex3fbuffer = NULL;
8194         rsurface.batchelement3i = NULL;
8195         rsurface.batchelement3i_indexbuffer = NULL;
8196         rsurface.batchelement3i_bufferoffset = 0;
8197         rsurface.batchelement3s = NULL;
8198         rsurface.batchelement3s_indexbuffer = NULL;
8199         rsurface.batchelement3s_bufferoffset = 0;
8200         rsurface.passcolor4f = NULL;
8201         rsurface.passcolor4f_vertexbuffer = NULL;
8202         rsurface.passcolor4f_bufferoffset = 0;
8203 }
8204
8205 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8206 {
8207         dp_model_t *model = ent->model;
8208         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8209         //      return;
8210         rsurface.entity = (entity_render_t *)ent;
8211         rsurface.skeleton = ent->skeleton;
8212         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8213         rsurface.ent_skinnum = ent->skinnum;
8214         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;
8215         rsurface.ent_flags = ent->flags;
8216         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8217         rsurface.matrix = ent->matrix;
8218         rsurface.inversematrix = ent->inversematrix;
8219         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8220         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8221         R_EntityMatrix(&rsurface.matrix);
8222         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8223         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8224         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8225         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8226         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8227         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8228         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8229         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8230         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8231         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8232         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8233         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8234         rsurface.colormod[3] = ent->alpha;
8235         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8236         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8237         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8238         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8239         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8240         if (ent->model->brush.submodel && !prepass)
8241         {
8242                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8243                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8244         }
8245         if (model->surfmesh.isanimated && model->AnimateVertices)
8246         {
8247                 if (ent->animcache_vertex3f)
8248                 {
8249                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8250                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8251                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8252                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8253                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8254                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8255                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8256                 }
8257                 else if (wanttangents)
8258                 {
8259                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8260                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8261                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8262                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8263                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8264                         rsurface.modelvertexmesh = NULL;
8265                         rsurface.modelvertexmeshbuffer = NULL;
8266                         rsurface.modelvertex3fbuffer = NULL;
8267                 }
8268                 else if (wantnormals)
8269                 {
8270                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8271                         rsurface.modelsvector3f = NULL;
8272                         rsurface.modeltvector3f = NULL;
8273                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8274                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8275                         rsurface.modelvertexmesh = NULL;
8276                         rsurface.modelvertexmeshbuffer = NULL;
8277                         rsurface.modelvertex3fbuffer = NULL;
8278                 }
8279                 else
8280                 {
8281                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8282                         rsurface.modelsvector3f = NULL;
8283                         rsurface.modeltvector3f = NULL;
8284                         rsurface.modelnormal3f = NULL;
8285                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8286                         rsurface.modelvertexmesh = NULL;
8287                         rsurface.modelvertexmeshbuffer = NULL;
8288                         rsurface.modelvertex3fbuffer = NULL;
8289                 }
8290                 rsurface.modelvertex3f_vertexbuffer = 0;
8291                 rsurface.modelvertex3f_bufferoffset = 0;
8292                 rsurface.modelsvector3f_vertexbuffer = 0;
8293                 rsurface.modelsvector3f_bufferoffset = 0;
8294                 rsurface.modeltvector3f_vertexbuffer = 0;
8295                 rsurface.modeltvector3f_bufferoffset = 0;
8296                 rsurface.modelnormal3f_vertexbuffer = 0;
8297                 rsurface.modelnormal3f_bufferoffset = 0;
8298                 rsurface.modelgeneratedvertex = true;
8299         }
8300         else
8301         {
8302                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8303                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8304                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8305                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8306                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8307                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8308                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8309                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8310                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8311                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8312                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8313                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8314                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8315                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8316                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8317                 rsurface.modelgeneratedvertex = false;
8318         }
8319         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8320         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8321         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8322         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8323         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8324         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8325         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8326         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8327         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8328         rsurface.modelelement3i = model->surfmesh.data_element3i;
8329         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8330         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8331         rsurface.modelelement3s = model->surfmesh.data_element3s;
8332         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8333         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8334         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8335         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8336         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8337         rsurface.modelsurfaces = model->data_surfaces;
8338         rsurface.batchgeneratedvertex = false;
8339         rsurface.batchfirstvertex = 0;
8340         rsurface.batchnumvertices = 0;
8341         rsurface.batchfirsttriangle = 0;
8342         rsurface.batchnumtriangles = 0;
8343         rsurface.batchvertex3f  = NULL;
8344         rsurface.batchvertex3f_vertexbuffer = NULL;
8345         rsurface.batchvertex3f_bufferoffset = 0;
8346         rsurface.batchsvector3f = NULL;
8347         rsurface.batchsvector3f_vertexbuffer = NULL;
8348         rsurface.batchsvector3f_bufferoffset = 0;
8349         rsurface.batchtvector3f = NULL;
8350         rsurface.batchtvector3f_vertexbuffer = NULL;
8351         rsurface.batchtvector3f_bufferoffset = 0;
8352         rsurface.batchnormal3f  = NULL;
8353         rsurface.batchnormal3f_vertexbuffer = NULL;
8354         rsurface.batchnormal3f_bufferoffset = 0;
8355         rsurface.batchlightmapcolor4f = NULL;
8356         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8357         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8358         rsurface.batchtexcoordtexture2f = NULL;
8359         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8360         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8361         rsurface.batchtexcoordlightmap2f = NULL;
8362         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8363         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8364         rsurface.batchvertexmesh = NULL;
8365         rsurface.batchvertexmeshbuffer = NULL;
8366         rsurface.batchvertex3fbuffer = NULL;
8367         rsurface.batchelement3i = NULL;
8368         rsurface.batchelement3i_indexbuffer = NULL;
8369         rsurface.batchelement3i_bufferoffset = 0;
8370         rsurface.batchelement3s = NULL;
8371         rsurface.batchelement3s_indexbuffer = NULL;
8372         rsurface.batchelement3s_bufferoffset = 0;
8373         rsurface.passcolor4f = NULL;
8374         rsurface.passcolor4f_vertexbuffer = NULL;
8375         rsurface.passcolor4f_bufferoffset = 0;
8376 }
8377
8378 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)
8379 {
8380         rsurface.entity = r_refdef.scene.worldentity;
8381         rsurface.skeleton = NULL;
8382         rsurface.ent_skinnum = 0;
8383         rsurface.ent_qwskin = -1;
8384         rsurface.ent_flags = entflags;
8385         rsurface.shadertime = r_refdef.scene.time - shadertime;
8386         rsurface.modelnumvertices = numvertices;
8387         rsurface.modelnumtriangles = numtriangles;
8388         rsurface.matrix = *matrix;
8389         rsurface.inversematrix = *inversematrix;
8390         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8391         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8392         R_EntityMatrix(&rsurface.matrix);
8393         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8394         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8395         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8396         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8397         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8398         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8399         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8400         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8401         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8402         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8403         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8404         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8405         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);
8406         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8407         rsurface.frameblend[0].lerp = 1;
8408         rsurface.ent_alttextures = false;
8409         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8410         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8411         if (wanttangents)
8412         {
8413                 rsurface.modelvertex3f = (float *)vertex3f;
8414                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8415                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8416                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8417         }
8418         else if (wantnormals)
8419         {
8420                 rsurface.modelvertex3f = (float *)vertex3f;
8421                 rsurface.modelsvector3f = NULL;
8422                 rsurface.modeltvector3f = NULL;
8423                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8424         }
8425         else
8426         {
8427                 rsurface.modelvertex3f = (float *)vertex3f;
8428                 rsurface.modelsvector3f = NULL;
8429                 rsurface.modeltvector3f = NULL;
8430                 rsurface.modelnormal3f = NULL;
8431         }
8432         rsurface.modelvertexmesh = NULL;
8433         rsurface.modelvertexmeshbuffer = NULL;
8434         rsurface.modelvertex3fbuffer = NULL;
8435         rsurface.modelvertex3f_vertexbuffer = 0;
8436         rsurface.modelvertex3f_bufferoffset = 0;
8437         rsurface.modelsvector3f_vertexbuffer = 0;
8438         rsurface.modelsvector3f_bufferoffset = 0;
8439         rsurface.modeltvector3f_vertexbuffer = 0;
8440         rsurface.modeltvector3f_bufferoffset = 0;
8441         rsurface.modelnormal3f_vertexbuffer = 0;
8442         rsurface.modelnormal3f_bufferoffset = 0;
8443         rsurface.modelgeneratedvertex = true;
8444         rsurface.modellightmapcolor4f  = (float *)color4f;
8445         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8446         rsurface.modellightmapcolor4f_bufferoffset = 0;
8447         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8448         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8449         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8450         rsurface.modeltexcoordlightmap2f  = NULL;
8451         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8452         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8453         rsurface.modelelement3i = (int *)element3i;
8454         rsurface.modelelement3i_indexbuffer = NULL;
8455         rsurface.modelelement3i_bufferoffset = 0;
8456         rsurface.modelelement3s = (unsigned short *)element3s;
8457         rsurface.modelelement3s_indexbuffer = NULL;
8458         rsurface.modelelement3s_bufferoffset = 0;
8459         rsurface.modellightmapoffsets = NULL;
8460         rsurface.modelsurfaces = NULL;
8461         rsurface.batchgeneratedvertex = false;
8462         rsurface.batchfirstvertex = 0;
8463         rsurface.batchnumvertices = 0;
8464         rsurface.batchfirsttriangle = 0;
8465         rsurface.batchnumtriangles = 0;
8466         rsurface.batchvertex3f  = NULL;
8467         rsurface.batchvertex3f_vertexbuffer = NULL;
8468         rsurface.batchvertex3f_bufferoffset = 0;
8469         rsurface.batchsvector3f = NULL;
8470         rsurface.batchsvector3f_vertexbuffer = NULL;
8471         rsurface.batchsvector3f_bufferoffset = 0;
8472         rsurface.batchtvector3f = NULL;
8473         rsurface.batchtvector3f_vertexbuffer = NULL;
8474         rsurface.batchtvector3f_bufferoffset = 0;
8475         rsurface.batchnormal3f  = NULL;
8476         rsurface.batchnormal3f_vertexbuffer = NULL;
8477         rsurface.batchnormal3f_bufferoffset = 0;
8478         rsurface.batchlightmapcolor4f = NULL;
8479         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8480         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8481         rsurface.batchtexcoordtexture2f = NULL;
8482         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8483         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8484         rsurface.batchtexcoordlightmap2f = NULL;
8485         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8486         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8487         rsurface.batchvertexmesh = NULL;
8488         rsurface.batchvertexmeshbuffer = NULL;
8489         rsurface.batchvertex3fbuffer = NULL;
8490         rsurface.batchelement3i = NULL;
8491         rsurface.batchelement3i_indexbuffer = NULL;
8492         rsurface.batchelement3i_bufferoffset = 0;
8493         rsurface.batchelement3s = NULL;
8494         rsurface.batchelement3s_indexbuffer = NULL;
8495         rsurface.batchelement3s_bufferoffset = 0;
8496         rsurface.passcolor4f = NULL;
8497         rsurface.passcolor4f_vertexbuffer = NULL;
8498         rsurface.passcolor4f_bufferoffset = 0;
8499
8500         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8501         {
8502                 if ((wantnormals || wanttangents) && !normal3f)
8503                 {
8504                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8505                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8506                 }
8507                 if (wanttangents && !svector3f)
8508                 {
8509                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8510                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8511                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8512                 }
8513         }
8514 }
8515
8516 float RSurf_FogPoint(const float *v)
8517 {
8518         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8519         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8520         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8521         float FogHeightFade = r_refdef.fogheightfade;
8522         float fogfrac;
8523         unsigned int fogmasktableindex;
8524         if (r_refdef.fogplaneviewabove)
8525                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8526         else
8527                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8528         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8529         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8530 }
8531
8532 float RSurf_FogVertex(const float *v)
8533 {
8534         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8535         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8536         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8537         float FogHeightFade = rsurface.fogheightfade;
8538         float fogfrac;
8539         unsigned int fogmasktableindex;
8540         if (r_refdef.fogplaneviewabove)
8541                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8542         else
8543                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8544         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8545         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8546 }
8547
8548 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8549 {
8550         int i;
8551         for (i = 0;i < numelements;i++)
8552                 outelement3i[i] = inelement3i[i] + adjust;
8553 }
8554
8555 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8556 extern cvar_t gl_vbo;
8557 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8558 {
8559         int deformindex;
8560         int firsttriangle;
8561         int numtriangles;
8562         int firstvertex;
8563         int endvertex;
8564         int numvertices;
8565         int surfacefirsttriangle;
8566         int surfacenumtriangles;
8567         int surfacefirstvertex;
8568         int surfaceendvertex;
8569         int surfacenumvertices;
8570         int batchnumvertices;
8571         int batchnumtriangles;
8572         int needsupdate;
8573         int i, j;
8574         qboolean gaps;
8575         qboolean dynamicvertex;
8576         float amplitude;
8577         float animpos;
8578         float scale;
8579         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8580         float waveparms[4];
8581         q3shaderinfo_deform_t *deform;
8582         const msurface_t *surface, *firstsurface;
8583         r_vertexmesh_t *vertexmesh;
8584         if (!texturenumsurfaces)
8585                 return;
8586         // find vertex range of this surface batch
8587         gaps = false;
8588         firstsurface = texturesurfacelist[0];
8589         firsttriangle = firstsurface->num_firsttriangle;
8590         batchnumvertices = 0;
8591         batchnumtriangles = 0;
8592         firstvertex = endvertex = firstsurface->num_firstvertex;
8593         for (i = 0;i < texturenumsurfaces;i++)
8594         {
8595                 surface = texturesurfacelist[i];
8596                 if (surface != firstsurface + i)
8597                         gaps = true;
8598                 surfacefirstvertex = surface->num_firstvertex;
8599                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8600                 surfacenumvertices = surface->num_vertices;
8601                 surfacenumtriangles = surface->num_triangles;
8602                 if (firstvertex > surfacefirstvertex)
8603                         firstvertex = surfacefirstvertex;
8604                 if (endvertex < surfaceendvertex)
8605                         endvertex = surfaceendvertex;
8606                 batchnumvertices += surfacenumvertices;
8607                 batchnumtriangles += surfacenumtriangles;
8608         }
8609
8610         // we now know the vertex range used, and if there are any gaps in it
8611         rsurface.batchfirstvertex = firstvertex;
8612         rsurface.batchnumvertices = endvertex - firstvertex;
8613         rsurface.batchfirsttriangle = firsttriangle;
8614         rsurface.batchnumtriangles = batchnumtriangles;
8615
8616         // this variable holds flags for which properties have been updated that
8617         // may require regenerating vertexmesh array...
8618         needsupdate = 0;
8619
8620         // check if any dynamic vertex processing must occur
8621         dynamicvertex = false;
8622
8623         // if there is a chance of animated vertex colors, it's a dynamic batch
8624         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8625         {
8626                 dynamicvertex = true;
8627                 batchneed |= BATCHNEED_NOGAPS;
8628                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8629         }
8630
8631         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8632         {
8633                 switch (deform->deform)
8634                 {
8635                 default:
8636                 case Q3DEFORM_PROJECTIONSHADOW:
8637                 case Q3DEFORM_TEXT0:
8638                 case Q3DEFORM_TEXT1:
8639                 case Q3DEFORM_TEXT2:
8640                 case Q3DEFORM_TEXT3:
8641                 case Q3DEFORM_TEXT4:
8642                 case Q3DEFORM_TEXT5:
8643                 case Q3DEFORM_TEXT6:
8644                 case Q3DEFORM_TEXT7:
8645                 case Q3DEFORM_NONE:
8646                         break;
8647                 case Q3DEFORM_AUTOSPRITE:
8648                         dynamicvertex = true;
8649                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8650                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8651                         break;
8652                 case Q3DEFORM_AUTOSPRITE2:
8653                         dynamicvertex = true;
8654                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8655                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8656                         break;
8657                 case Q3DEFORM_NORMAL:
8658                         dynamicvertex = true;
8659                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8660                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8661                         break;
8662                 case Q3DEFORM_WAVE:
8663                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8664                                 break; // if wavefunc is a nop, ignore this transform
8665                         dynamicvertex = true;
8666                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8667                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8668                         break;
8669                 case Q3DEFORM_BULGE:
8670                         dynamicvertex = true;
8671                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8672                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8673                         break;
8674                 case Q3DEFORM_MOVE:
8675                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8676                                 break; // if wavefunc is a nop, ignore this transform
8677                         dynamicvertex = true;
8678                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8679                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8680                         break;
8681                 }
8682         }
8683         switch(rsurface.texture->tcgen.tcgen)
8684         {
8685         default:
8686         case Q3TCGEN_TEXTURE:
8687                 break;
8688         case Q3TCGEN_LIGHTMAP:
8689                 dynamicvertex = true;
8690                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8691                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8692                 break;
8693         case Q3TCGEN_VECTOR:
8694                 dynamicvertex = true;
8695                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8696                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8697                 break;
8698         case Q3TCGEN_ENVIRONMENT:
8699                 dynamicvertex = true;
8700                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8701                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8702                 break;
8703         }
8704         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8705         {
8706                 dynamicvertex = true;
8707                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8708                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8709         }
8710
8711         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8712         {
8713                 dynamicvertex = true;
8714                 batchneed |= BATCHNEED_NOGAPS;
8715                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8716         }
8717
8718         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8719         {
8720                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8721                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8722                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8723                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8724                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8725                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8726                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8727         }
8728
8729         // when the model data has no vertex buffer (dynamic mesh), we need to
8730         // eliminate gaps
8731         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8732                 batchneed |= BATCHNEED_NOGAPS;
8733
8734         // if needsupdate, we have to do a dynamic vertex batch for sure
8735         if (needsupdate & batchneed)
8736                 dynamicvertex = true;
8737
8738         // see if we need to build vertexmesh from arrays
8739         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8740                 dynamicvertex = true;
8741
8742         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8743         // also some drivers strongly dislike firstvertex
8744         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8745                 dynamicvertex = true;
8746
8747         rsurface.batchvertex3f = rsurface.modelvertex3f;
8748         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8749         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8750         rsurface.batchsvector3f = rsurface.modelsvector3f;
8751         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8752         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8753         rsurface.batchtvector3f = rsurface.modeltvector3f;
8754         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8755         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8756         rsurface.batchnormal3f = rsurface.modelnormal3f;
8757         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8758         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8759         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8760         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8761         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8762         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8763         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8764         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8765         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8766         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8767         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8768         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8769         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8770         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8771         rsurface.batchelement3i = rsurface.modelelement3i;
8772         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8773         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8774         rsurface.batchelement3s = rsurface.modelelement3s;
8775         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8776         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8777
8778         // if any dynamic vertex processing has to occur in software, we copy the
8779         // entire surface list together before processing to rebase the vertices
8780         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8781         //
8782         // if any gaps exist and we do not have a static vertex buffer, we have to
8783         // copy the surface list together to avoid wasting upload bandwidth on the
8784         // vertices in the gaps.
8785         //
8786         // if gaps exist and we have a static vertex buffer, we still have to
8787         // combine the index buffer ranges into one dynamic index buffer.
8788         //
8789         // in all cases we end up with data that can be drawn in one call.
8790
8791         if (!dynamicvertex)
8792         {
8793                 // static vertex data, just set pointers...
8794                 rsurface.batchgeneratedvertex = false;
8795                 // if there are gaps, we want to build a combined index buffer,
8796                 // otherwise use the original static buffer with an appropriate offset
8797                 if (gaps)
8798                 {
8799                         // build a new triangle elements array for this batch
8800                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8801                         rsurface.batchfirsttriangle = 0;
8802                         numtriangles = 0;
8803                         for (i = 0;i < texturenumsurfaces;i++)
8804                         {
8805                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8806                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8807                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8808                                 numtriangles += surfacenumtriangles;
8809                         }
8810                         rsurface.batchelement3i_indexbuffer = NULL;
8811                         rsurface.batchelement3i_bufferoffset = 0;
8812                         rsurface.batchelement3s = NULL;
8813                         rsurface.batchelement3s_indexbuffer = NULL;
8814                         rsurface.batchelement3s_bufferoffset = 0;
8815                         if (endvertex <= 65536)
8816                         {
8817                                 // make a 16bit (unsigned short) index array if possible
8818                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8819                                 for (i = 0;i < numtriangles*3;i++)
8820                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8821                         }
8822                 }
8823                 return;
8824         }
8825
8826         // something needs software processing, do it for real...
8827         // we only directly handle separate array data in this case and then
8828         // generate interleaved data if needed...
8829         rsurface.batchgeneratedvertex = true;
8830
8831         // now copy the vertex data into a combined array and make an index array
8832         // (this is what Quake3 does all the time)
8833         //if (gaps || rsurface.batchfirstvertex)
8834         {
8835                 rsurface.batchvertex3fbuffer = NULL;
8836                 rsurface.batchvertexmesh = NULL;
8837                 rsurface.batchvertexmeshbuffer = NULL;
8838                 rsurface.batchvertex3f = NULL;
8839                 rsurface.batchvertex3f_vertexbuffer = NULL;
8840                 rsurface.batchvertex3f_bufferoffset = 0;
8841                 rsurface.batchsvector3f = NULL;
8842                 rsurface.batchsvector3f_vertexbuffer = NULL;
8843                 rsurface.batchsvector3f_bufferoffset = 0;
8844                 rsurface.batchtvector3f = NULL;
8845                 rsurface.batchtvector3f_vertexbuffer = NULL;
8846                 rsurface.batchtvector3f_bufferoffset = 0;
8847                 rsurface.batchnormal3f = NULL;
8848                 rsurface.batchnormal3f_vertexbuffer = NULL;
8849                 rsurface.batchnormal3f_bufferoffset = 0;
8850                 rsurface.batchlightmapcolor4f = NULL;
8851                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8852                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8853                 rsurface.batchtexcoordtexture2f = NULL;
8854                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8855                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8856                 rsurface.batchtexcoordlightmap2f = NULL;
8857                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8858                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8859                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8860                 rsurface.batchelement3i_indexbuffer = NULL;
8861                 rsurface.batchelement3i_bufferoffset = 0;
8862                 rsurface.batchelement3s = NULL;
8863                 rsurface.batchelement3s_indexbuffer = NULL;
8864                 rsurface.batchelement3s_bufferoffset = 0;
8865                 // we'll only be setting up certain arrays as needed
8866                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8867                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8868                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8869                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8870                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8871                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8872                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8873                 {
8874                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8875                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8876                 }
8877                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8878                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8879                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8880                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8881                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8882                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8883                 numvertices = 0;
8884                 numtriangles = 0;
8885                 for (i = 0;i < texturenumsurfaces;i++)
8886                 {
8887                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8888                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8889                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8890                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8891                         // copy only the data requested
8892                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8893                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8894                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8895                         {
8896                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8897                                 {
8898                                         if (rsurface.batchvertex3f)
8899                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8900                                         else
8901                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8902                                 }
8903                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8904                                 {
8905                                         if (rsurface.modelnormal3f)
8906                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8907                                         else
8908                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8909                                 }
8910                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8911                                 {
8912                                         if (rsurface.modelsvector3f)
8913                                         {
8914                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8915                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8916                                         }
8917                                         else
8918                                         {
8919                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8920                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8921                                         }
8922                                 }
8923                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8924                                 {
8925                                         if (rsurface.modellightmapcolor4f)
8926                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8927                                         else
8928                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8929                                 }
8930                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8931                                 {
8932                                         if (rsurface.modeltexcoordtexture2f)
8933                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8934                                         else
8935                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8936                                 }
8937                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8938                                 {
8939                                         if (rsurface.modeltexcoordlightmap2f)
8940                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8941                                         else
8942                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8943                                 }
8944                         }
8945                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8946                         numvertices += surfacenumvertices;
8947                         numtriangles += surfacenumtriangles;
8948                 }
8949
8950                 // generate a 16bit index array as well if possible
8951                 // (in general, dynamic batches fit)
8952                 if (numvertices <= 65536)
8953                 {
8954                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8955                         for (i = 0;i < numtriangles*3;i++)
8956                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8957                 }
8958
8959                 // since we've copied everything, the batch now starts at 0
8960                 rsurface.batchfirstvertex = 0;
8961                 rsurface.batchnumvertices = batchnumvertices;
8962                 rsurface.batchfirsttriangle = 0;
8963                 rsurface.batchnumtriangles = batchnumtriangles;
8964         }
8965
8966         // q1bsp surfaces rendered in vertex color mode have to have colors
8967         // calculated based on lightstyles
8968         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8969         {
8970                 // generate color arrays for the surfaces in this list
8971                 int c[4];
8972                 int scale;
8973                 int size3;
8974                 const int *offsets;
8975                 const unsigned char *lm;
8976                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8977                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8978                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8979                 numvertices = 0;
8980                 for (i = 0;i < texturenumsurfaces;i++)
8981                 {
8982                         surface = texturesurfacelist[i];
8983                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8984                         surfacenumvertices = surface->num_vertices;
8985                         if (surface->lightmapinfo->samples)
8986                         {
8987                                 for (j = 0;j < surfacenumvertices;j++)
8988                                 {
8989                                         lm = surface->lightmapinfo->samples + offsets[j];
8990                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8991                                         VectorScale(lm, scale, c);
8992                                         if (surface->lightmapinfo->styles[1] != 255)
8993                                         {
8994                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8995                                                 lm += size3;
8996                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8997                                                 VectorMA(c, scale, lm, c);
8998                                                 if (surface->lightmapinfo->styles[2] != 255)
8999                                                 {
9000                                                         lm += size3;
9001                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9002                                                         VectorMA(c, scale, lm, c);
9003                                                         if (surface->lightmapinfo->styles[3] != 255)
9004                                                         {
9005                                                                 lm += size3;
9006                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9007                                                                 VectorMA(c, scale, lm, c);
9008                                                         }
9009                                                 }
9010                                         }
9011                                         c[0] >>= 7;
9012                                         c[1] >>= 7;
9013                                         c[2] >>= 7;
9014                                         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);
9015                                         numvertices++;
9016                                 }
9017                         }
9018                         else
9019                         {
9020                                 for (j = 0;j < surfacenumvertices;j++)
9021                                 {
9022                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9023                                         numvertices++;
9024                                 }
9025                         }
9026                 }
9027         }
9028
9029         // if vertices are deformed (sprite flares and things in maps, possibly
9030         // water waves, bulges and other deformations), modify the copied vertices
9031         // in place
9032         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9033         {
9034                 switch (deform->deform)
9035                 {
9036                 default:
9037                 case Q3DEFORM_PROJECTIONSHADOW:
9038                 case Q3DEFORM_TEXT0:
9039                 case Q3DEFORM_TEXT1:
9040                 case Q3DEFORM_TEXT2:
9041                 case Q3DEFORM_TEXT3:
9042                 case Q3DEFORM_TEXT4:
9043                 case Q3DEFORM_TEXT5:
9044                 case Q3DEFORM_TEXT6:
9045                 case Q3DEFORM_TEXT7:
9046                 case Q3DEFORM_NONE:
9047                         break;
9048                 case Q3DEFORM_AUTOSPRITE:
9049                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9050                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9051                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9052                         VectorNormalize(newforward);
9053                         VectorNormalize(newright);
9054                         VectorNormalize(newup);
9055 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9056 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9057 //                      rsurface.batchvertex3f_bufferoffset = 0;
9058 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9059 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9060 //                      rsurface.batchsvector3f_bufferoffset = 0;
9061 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9062 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9063 //                      rsurface.batchtvector3f_bufferoffset = 0;
9064 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9065 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9066 //                      rsurface.batchnormal3f_bufferoffset = 0;
9067                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9068                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9069                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9070                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9071                                 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);
9072                         // a single autosprite surface can contain multiple sprites...
9073                         for (j = 0;j < batchnumvertices - 3;j += 4)
9074                         {
9075                                 VectorClear(center);
9076                                 for (i = 0;i < 4;i++)
9077                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9078                                 VectorScale(center, 0.25f, center);
9079                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9080                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9081                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9082                                 for (i = 0;i < 4;i++)
9083                                 {
9084                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9085                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9086                                 }
9087                         }
9088                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9089                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9090                         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);
9091                         break;
9092                 case Q3DEFORM_AUTOSPRITE2:
9093                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9094                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9095                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9096                         VectorNormalize(newforward);
9097                         VectorNormalize(newright);
9098                         VectorNormalize(newup);
9099 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9100 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9101 //                      rsurface.batchvertex3f_bufferoffset = 0;
9102                         {
9103                                 const float *v1, *v2;
9104                                 vec3_t start, end;
9105                                 float f, l;
9106                                 struct
9107                                 {
9108                                         float length2;
9109                                         const float *v1;
9110                                         const float *v2;
9111                                 }
9112                                 shortest[2];
9113                                 memset(shortest, 0, sizeof(shortest));
9114                                 // a single autosprite surface can contain multiple sprites...
9115                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9116                                 {
9117                                         VectorClear(center);
9118                                         for (i = 0;i < 4;i++)
9119                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9120                                         VectorScale(center, 0.25f, center);
9121                                         // find the two shortest edges, then use them to define the
9122                                         // axis vectors for rotating around the central axis
9123                                         for (i = 0;i < 6;i++)
9124                                         {
9125                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9126                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9127                                                 l = VectorDistance2(v1, v2);
9128                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9129                                                 if (v1[2] != v2[2])
9130                                                         l += (1.0f / 1024.0f);
9131                                                 if (shortest[0].length2 > l || i == 0)
9132                                                 {
9133                                                         shortest[1] = shortest[0];
9134                                                         shortest[0].length2 = l;
9135                                                         shortest[0].v1 = v1;
9136                                                         shortest[0].v2 = v2;
9137                                                 }
9138                                                 else if (shortest[1].length2 > l || i == 1)
9139                                                 {
9140                                                         shortest[1].length2 = l;
9141                                                         shortest[1].v1 = v1;
9142                                                         shortest[1].v2 = v2;
9143                                                 }
9144                                         }
9145                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9146                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9147                                         // this calculates the right vector from the shortest edge
9148                                         // and the up vector from the edge midpoints
9149                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9150                                         VectorNormalize(right);
9151                                         VectorSubtract(end, start, up);
9152                                         VectorNormalize(up);
9153                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9154                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9155                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9156                                         VectorNegate(forward, forward);
9157                                         VectorReflect(forward, 0, up, forward);
9158                                         VectorNormalize(forward);
9159                                         CrossProduct(up, forward, newright);
9160                                         VectorNormalize(newright);
9161                                         // rotate the quad around the up axis vector, this is made
9162                                         // especially easy by the fact we know the quad is flat,
9163                                         // so we only have to subtract the center position and
9164                                         // measure distance along the right vector, and then
9165                                         // multiply that by the newright vector and add back the
9166                                         // center position
9167                                         // we also need to subtract the old position to undo the
9168                                         // displacement from the center, which we do with a
9169                                         // DotProduct, the subtraction/addition of center is also
9170                                         // optimized into DotProducts here
9171                                         l = DotProduct(right, center);
9172                                         for (i = 0;i < 4;i++)
9173                                         {
9174                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9175                                                 f = DotProduct(right, v1) - l;
9176                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9177                                         }
9178                                 }
9179                         }
9180                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9181                         {
9182 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9183 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9184 //                              rsurface.batchnormal3f_bufferoffset = 0;
9185                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9186                         }
9187                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9188                         {
9189 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9190 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9191 //                              rsurface.batchsvector3f_bufferoffset = 0;
9192 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9193 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9194 //                              rsurface.batchtvector3f_bufferoffset = 0;
9195                                 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);
9196                         }
9197                         break;
9198                 case Q3DEFORM_NORMAL:
9199                         // deform the normals to make reflections wavey
9200                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9201                         rsurface.batchnormal3f_vertexbuffer = NULL;
9202                         rsurface.batchnormal3f_bufferoffset = 0;
9203                         for (j = 0;j < batchnumvertices;j++)
9204                         {
9205                                 float vertex[3];
9206                                 float *normal = rsurface.batchnormal3f + 3*j;
9207                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9208                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9209                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9210                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9211                                 VectorNormalize(normal);
9212                         }
9213                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9214                         {
9215 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9216 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9217 //                              rsurface.batchsvector3f_bufferoffset = 0;
9218 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9219 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9220 //                              rsurface.batchtvector3f_bufferoffset = 0;
9221                                 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);
9222                         }
9223                         break;
9224                 case Q3DEFORM_WAVE:
9225                         // deform vertex array to make wavey water and flags and such
9226                         waveparms[0] = deform->waveparms[0];
9227                         waveparms[1] = deform->waveparms[1];
9228                         waveparms[2] = deform->waveparms[2];
9229                         waveparms[3] = deform->waveparms[3];
9230                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9231                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9232                         // this is how a divisor of vertex influence on deformation
9233                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9234                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9235 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9236 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9237 //                      rsurface.batchvertex3f_bufferoffset = 0;
9238 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9239 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9240 //                      rsurface.batchnormal3f_bufferoffset = 0;
9241                         for (j = 0;j < batchnumvertices;j++)
9242                         {
9243                                 // if the wavefunc depends on time, evaluate it per-vertex
9244                                 if (waveparms[3])
9245                                 {
9246                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9247                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9248                                 }
9249                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9250                         }
9251                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9252                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9253                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9254                         {
9255 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9256 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9257 //                              rsurface.batchsvector3f_bufferoffset = 0;
9258 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9259 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9260 //                              rsurface.batchtvector3f_bufferoffset = 0;
9261                                 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);
9262                         }
9263                         break;
9264                 case Q3DEFORM_BULGE:
9265                         // deform vertex array to make the surface have moving bulges
9266 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9267 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9268 //                      rsurface.batchvertex3f_bufferoffset = 0;
9269 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9270 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9271 //                      rsurface.batchnormal3f_bufferoffset = 0;
9272                         for (j = 0;j < batchnumvertices;j++)
9273                         {
9274                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9275                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9276                         }
9277                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9278                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9279                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9280                         {
9281 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9282 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9283 //                              rsurface.batchsvector3f_bufferoffset = 0;
9284 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9285 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9286 //                              rsurface.batchtvector3f_bufferoffset = 0;
9287                                 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);
9288                         }
9289                         break;
9290                 case Q3DEFORM_MOVE:
9291                         // deform vertex array
9292                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9293                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9294                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9295                         VectorScale(deform->parms, scale, waveparms);
9296 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9297 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9298 //                      rsurface.batchvertex3f_bufferoffset = 0;
9299                         for (j = 0;j < batchnumvertices;j++)
9300                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9301                         break;
9302                 }
9303         }
9304
9305         // generate texcoords based on the chosen texcoord source
9306         switch(rsurface.texture->tcgen.tcgen)
9307         {
9308         default:
9309         case Q3TCGEN_TEXTURE:
9310                 break;
9311         case Q3TCGEN_LIGHTMAP:
9312 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9313 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9314 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9315                 if (rsurface.batchtexcoordlightmap2f)
9316                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9317                 break;
9318         case Q3TCGEN_VECTOR:
9319 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9320 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9321 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9322                 for (j = 0;j < batchnumvertices;j++)
9323                 {
9324                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9325                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9326                 }
9327                 break;
9328         case Q3TCGEN_ENVIRONMENT:
9329                 // make environment reflections using a spheremap
9330                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9331                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9332                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9333                 for (j = 0;j < batchnumvertices;j++)
9334                 {
9335                         // identical to Q3A's method, but executed in worldspace so
9336                         // carried models can be shiny too
9337
9338                         float viewer[3], d, reflected[3], worldreflected[3];
9339
9340                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9341                         // VectorNormalize(viewer);
9342
9343                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9344
9345                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9346                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9347                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9348                         // note: this is proportinal to viewer, so we can normalize later
9349
9350                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9351                         VectorNormalize(worldreflected);
9352
9353                         // note: this sphere map only uses world x and z!
9354                         // so positive and negative y will LOOK THE SAME.
9355                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9356                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9357                 }
9358                 break;
9359         }
9360         // the only tcmod that needs software vertex processing is turbulent, so
9361         // check for it here and apply the changes if needed
9362         // and we only support that as the first one
9363         // (handling a mixture of turbulent and other tcmods would be problematic
9364         //  without punting it entirely to a software path)
9365         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9366         {
9367                 amplitude = rsurface.texture->tcmods[0].parms[1];
9368                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9369 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9370 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9371 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9372                 for (j = 0;j < batchnumvertices;j++)
9373                 {
9374                         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);
9375                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9376                 }
9377         }
9378
9379         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9380         {
9381                 // convert the modified arrays to vertex structs
9382 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9383 //              rsurface.batchvertexmeshbuffer = NULL;
9384                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9385                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9386                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9387                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9388                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9389                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9390                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9391                 {
9392                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9393                         {
9394                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9395                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9396                         }
9397                 }
9398                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9399                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9400                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9401                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9402                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9403                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9404                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9405                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9406                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9407         }
9408 }
9409
9410 void RSurf_DrawBatch(void)
9411 {
9412         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9413         // through the pipeline, killing it earlier in the pipeline would have
9414         // per-surface overhead rather than per-batch overhead, so it's best to
9415         // reject it here, before it hits glDraw.
9416         if (rsurface.batchnumtriangles == 0)
9417                 return;
9418 #if 0
9419         // batch debugging code
9420         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9421         {
9422                 int i;
9423                 int j;
9424                 int c;
9425                 const int *e;
9426                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9427                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9428                 {
9429                         c = e[i];
9430                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9431                         {
9432                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9433                                 {
9434                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9435                                                 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);
9436                                         break;
9437                                 }
9438                         }
9439                 }
9440         }
9441 #endif
9442         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);
9443 }
9444
9445 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9446 {
9447         // pick the closest matching water plane
9448         int planeindex, vertexindex, bestplaneindex = -1;
9449         float d, bestd;
9450         vec3_t vert;
9451         const float *v;
9452         r_waterstate_waterplane_t *p;
9453         qboolean prepared = false;
9454         bestd = 0;
9455         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9456         {
9457                 if(p->camera_entity != rsurface.texture->camera_entity)
9458                         continue;
9459                 d = 0;
9460                 if(!prepared)
9461                 {
9462                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9463                         prepared = true;
9464                         if(rsurface.batchnumvertices == 0)
9465                                 break;
9466                 }
9467                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9468                 {
9469                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9470                         d += fabs(PlaneDiff(vert, &p->plane));
9471                 }
9472                 if (bestd > d || bestplaneindex < 0)
9473                 {
9474                         bestd = d;
9475                         bestplaneindex = planeindex;
9476                 }
9477         }
9478         return bestplaneindex;
9479         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9480         // this situation though, as it might be better to render single larger
9481         // batches with useless stuff (backface culled for example) than to
9482         // render multiple smaller batches
9483 }
9484
9485 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9486 {
9487         int i;
9488         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9489         rsurface.passcolor4f_vertexbuffer = 0;
9490         rsurface.passcolor4f_bufferoffset = 0;
9491         for (i = 0;i < rsurface.batchnumvertices;i++)
9492                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9493 }
9494
9495 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9496 {
9497         int i;
9498         float f;
9499         const float *v;
9500         const float *c;
9501         float *c2;
9502         if (rsurface.passcolor4f)
9503         {
9504                 // generate color arrays
9505                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9506                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9507                 rsurface.passcolor4f_vertexbuffer = 0;
9508                 rsurface.passcolor4f_bufferoffset = 0;
9509                 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)
9510                 {
9511                         f = RSurf_FogVertex(v);
9512                         c2[0] = c[0] * f;
9513                         c2[1] = c[1] * f;
9514                         c2[2] = c[2] * f;
9515                         c2[3] = c[3];
9516                 }
9517         }
9518         else
9519         {
9520                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9521                 rsurface.passcolor4f_vertexbuffer = 0;
9522                 rsurface.passcolor4f_bufferoffset = 0;
9523                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9524                 {
9525                         f = RSurf_FogVertex(v);
9526                         c2[0] = f;
9527                         c2[1] = f;
9528                         c2[2] = f;
9529                         c2[3] = 1;
9530                 }
9531         }
9532 }
9533
9534 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9535 {
9536         int i;
9537         float f;
9538         const float *v;
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, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9548         {
9549                 f = RSurf_FogVertex(v);
9550                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9551                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9552                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9553                 c2[3] = c[3];
9554         }
9555 }
9556
9557 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9558 {
9559         int i;
9560         const float *c;
9561         float *c2;
9562         if (!rsurface.passcolor4f)
9563                 return;
9564         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9565         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9566         rsurface.passcolor4f_vertexbuffer = 0;
9567         rsurface.passcolor4f_bufferoffset = 0;
9568         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9569         {
9570                 c2[0] = c[0] * r;
9571                 c2[1] = c[1] * g;
9572                 c2[2] = c[2] * b;
9573                 c2[3] = c[3] * a;
9574         }
9575 }
9576
9577 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9578 {
9579         int i;
9580         const float *c;
9581         float *c2;
9582         if (!rsurface.passcolor4f)
9583                 return;
9584         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9585         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9586         rsurface.passcolor4f_vertexbuffer = 0;
9587         rsurface.passcolor4f_bufferoffset = 0;
9588         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9589         {
9590                 c2[0] = c[0] + r_refdef.scene.ambient;
9591                 c2[1] = c[1] + r_refdef.scene.ambient;
9592                 c2[2] = c[2] + r_refdef.scene.ambient;
9593                 c2[3] = c[3];
9594         }
9595 }
9596
9597 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9598 {
9599         // TODO: optimize
9600         rsurface.passcolor4f = NULL;
9601         rsurface.passcolor4f_vertexbuffer = 0;
9602         rsurface.passcolor4f_bufferoffset = 0;
9603         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9604         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9605         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9606         GL_Color(r, g, b, a);
9607         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9608         RSurf_DrawBatch();
9609 }
9610
9611 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9612 {
9613         // TODO: optimize applyfog && applycolor case
9614         // just apply fog if necessary, and tint the fog color array if necessary
9615         rsurface.passcolor4f = NULL;
9616         rsurface.passcolor4f_vertexbuffer = 0;
9617         rsurface.passcolor4f_bufferoffset = 0;
9618         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9619         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9620         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9621         GL_Color(r, g, b, a);
9622         RSurf_DrawBatch();
9623 }
9624
9625 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9626 {
9627         // TODO: optimize
9628         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9629         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9630         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9631         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9632         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9633         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9634         GL_Color(r, g, b, a);
9635         RSurf_DrawBatch();
9636 }
9637
9638 static void RSurf_DrawBatch_GL11_ClampColor(void)
9639 {
9640         int i;
9641         const float *c1;
9642         float *c2;
9643         if (!rsurface.passcolor4f)
9644                 return;
9645         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9646         {
9647                 c2[0] = bound(0.0f, c1[0], 1.0f);
9648                 c2[1] = bound(0.0f, c1[1], 1.0f);
9649                 c2[2] = bound(0.0f, c1[2], 1.0f);
9650                 c2[3] = bound(0.0f, c1[3], 1.0f);
9651         }
9652 }
9653
9654 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9655 {
9656         int i;
9657         float f;
9658         const float *v;
9659         const float *n;
9660         float *c;
9661         //vec3_t eyedir;
9662
9663         // fake shading
9664         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9665         rsurface.passcolor4f_vertexbuffer = 0;
9666         rsurface.passcolor4f_bufferoffset = 0;
9667         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9668         {
9669                 f = -DotProduct(r_refdef.view.forward, n);
9670                 f = max(0, f);
9671                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9672                 f *= r_refdef.lightmapintensity;
9673                 Vector4Set(c, f, f, f, 1);
9674         }
9675 }
9676
9677 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9678 {
9679         RSurf_DrawBatch_GL11_ApplyFakeLight();
9680         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9681         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9682         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9683         GL_Color(r, g, b, a);
9684         RSurf_DrawBatch();
9685 }
9686
9687 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9688 {
9689         int i;
9690         float f;
9691         float alpha;
9692         const float *v;
9693         const float *n;
9694         float *c;
9695         vec3_t ambientcolor;
9696         vec3_t diffusecolor;
9697         vec3_t lightdir;
9698         // TODO: optimize
9699         // model lighting
9700         VectorCopy(rsurface.modellight_lightdir, lightdir);
9701         f = 0.5f * r_refdef.lightmapintensity;
9702         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9703         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9704         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9705         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9706         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9707         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9708         alpha = *a;
9709         if (VectorLength2(diffusecolor) > 0)
9710         {
9711                 // q3-style directional shading
9712                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9713                 rsurface.passcolor4f_vertexbuffer = 0;
9714                 rsurface.passcolor4f_bufferoffset = 0;
9715                 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)
9716                 {
9717                         if ((f = DotProduct(n, lightdir)) > 0)
9718                                 VectorMA(ambientcolor, f, diffusecolor, c);
9719                         else
9720                                 VectorCopy(ambientcolor, c);
9721                         c[3] = alpha;
9722                 }
9723                 *r = 1;
9724                 *g = 1;
9725                 *b = 1;
9726                 *a = 1;
9727                 *applycolor = false;
9728         }
9729         else
9730         {
9731                 *r = ambientcolor[0];
9732                 *g = ambientcolor[1];
9733                 *b = ambientcolor[2];
9734                 rsurface.passcolor4f = NULL;
9735                 rsurface.passcolor4f_vertexbuffer = 0;
9736                 rsurface.passcolor4f_bufferoffset = 0;
9737         }
9738 }
9739
9740 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9741 {
9742         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9743         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9744         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9745         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9746         GL_Color(r, g, b, a);
9747         RSurf_DrawBatch();
9748 }
9749
9750 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9751 {
9752         int i;
9753         float f;
9754         const float *v;
9755         float *c;
9756
9757         // fake shading
9758         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9759         rsurface.passcolor4f_vertexbuffer = 0;
9760         rsurface.passcolor4f_bufferoffset = 0;
9761
9762         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9763         {
9764                 f = 1 - RSurf_FogVertex(v);
9765                 c[0] = r;
9766                 c[1] = g;
9767                 c[2] = b;
9768                 c[3] = f * a;
9769         }
9770 }
9771
9772 void RSurf_SetupDepthAndCulling(void)
9773 {
9774         // submodels are biased to avoid z-fighting with world surfaces that they
9775         // may be exactly overlapping (avoids z-fighting artifacts on certain
9776         // doors and things in Quake maps)
9777         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9778         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9779         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9780         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9781 }
9782
9783 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9784 {
9785         // transparent sky would be ridiculous
9786         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9787                 return;
9788         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9789         skyrenderlater = true;
9790         RSurf_SetupDepthAndCulling();
9791         GL_DepthMask(true);
9792         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9793         // skymasking on them, and Quake3 never did sky masking (unlike
9794         // software Quake and software Quake2), so disable the sky masking
9795         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9796         // and skymasking also looks very bad when noclipping outside the
9797         // level, so don't use it then either.
9798         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9799         {
9800                 R_Mesh_ResetTextureState();
9801                 if (skyrendermasked)
9802                 {
9803                         R_SetupShader_DepthOrShadow(false);
9804                         // depth-only (masking)
9805                         GL_ColorMask(0,0,0,0);
9806                         // just to make sure that braindead drivers don't draw
9807                         // anything despite that colormask...
9808                         GL_BlendFunc(GL_ZERO, GL_ONE);
9809                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9810                         if (rsurface.batchvertex3fbuffer)
9811                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9812                         else
9813                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9814                 }
9815                 else
9816                 {
9817                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9818                         // fog sky
9819                         GL_BlendFunc(GL_ONE, GL_ZERO);
9820                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9821                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9822                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9823                 }
9824                 RSurf_DrawBatch();
9825                 if (skyrendermasked)
9826                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9827         }
9828         R_Mesh_ResetTextureState();
9829         GL_Color(1, 1, 1, 1);
9830 }
9831
9832 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9833 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9834 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9835 {
9836         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9837                 return;
9838         if (prepass)
9839         {
9840                 // render screenspace normalmap to texture
9841                 GL_DepthMask(true);
9842                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9843                 RSurf_DrawBatch();
9844         }
9845
9846         // bind lightmap texture
9847
9848         // water/refraction/reflection/camera surfaces have to be handled specially
9849         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9850         {
9851                 int start, end, startplaneindex;
9852                 for (start = 0;start < texturenumsurfaces;start = end)
9853                 {
9854                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9855                         if(startplaneindex < 0)
9856                         {
9857                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9858                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9859                                 end = start + 1;
9860                                 continue;
9861                         }
9862                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9863                                 ;
9864                         // now that we have a batch using the same planeindex, render it
9865                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9866                         {
9867                                 // render water or distortion background
9868                                 GL_DepthMask(true);
9869                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9870                                 RSurf_DrawBatch();
9871                                 // blend surface on top
9872                                 GL_DepthMask(false);
9873                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9874                                 RSurf_DrawBatch();
9875                         }
9876                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9877                         {
9878                                 // render surface with reflection texture as input
9879                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9880                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9881                                 RSurf_DrawBatch();
9882                         }
9883                 }
9884                 return;
9885         }
9886
9887         // render surface batch normally
9888         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9889         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);
9890         RSurf_DrawBatch();
9891 }
9892
9893 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9894 {
9895         // OpenGL 1.3 path - anything not completely ancient
9896         qboolean applycolor;
9897         qboolean applyfog;
9898         int layerindex;
9899         const texturelayer_t *layer;
9900         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);
9901         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9902
9903         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9904         {
9905                 vec4_t layercolor;
9906                 int layertexrgbscale;
9907                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9908                 {
9909                         if (layerindex == 0)
9910                                 GL_AlphaTest(true);
9911                         else
9912                         {
9913                                 GL_AlphaTest(false);
9914                                 GL_DepthFunc(GL_EQUAL);
9915                         }
9916                 }
9917                 GL_DepthMask(layer->depthmask && writedepth);
9918                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9919                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9920                 {
9921                         layertexrgbscale = 4;
9922                         VectorScale(layer->color, 0.25f, layercolor);
9923                 }
9924                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9925                 {
9926                         layertexrgbscale = 2;
9927                         VectorScale(layer->color, 0.5f, layercolor);
9928                 }
9929                 else
9930                 {
9931                         layertexrgbscale = 1;
9932                         VectorScale(layer->color, 1.0f, layercolor);
9933                 }
9934                 layercolor[3] = layer->color[3];
9935                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9936                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9937                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9938                 switch (layer->type)
9939                 {
9940                 case TEXTURELAYERTYPE_LITTEXTURE:
9941                         // single-pass lightmapped texture with 2x rgbscale
9942                         R_Mesh_TexBind(0, r_texture_white);
9943                         R_Mesh_TexMatrix(0, NULL);
9944                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9945                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9946                         R_Mesh_TexBind(1, layer->texture);
9947                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9948                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9949                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9950                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9951                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9952                         else if (FAKELIGHT_ENABLED)
9953                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9954                         else if (rsurface.uselightmaptexture)
9955                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9956                         else
9957                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9958                         break;
9959                 case TEXTURELAYERTYPE_TEXTURE:
9960                         // singletexture unlit texture with transparency support
9961                         R_Mesh_TexBind(0, layer->texture);
9962                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9963                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9964                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9965                         R_Mesh_TexBind(1, 0);
9966                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9967                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9968                         break;
9969                 case TEXTURELAYERTYPE_FOG:
9970                         // singletexture fogging
9971                         if (layer->texture)
9972                         {
9973                                 R_Mesh_TexBind(0, layer->texture);
9974                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9975                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9976                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9977                         }
9978                         else
9979                         {
9980                                 R_Mesh_TexBind(0, 0);
9981                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9982                         }
9983                         R_Mesh_TexBind(1, 0);
9984                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9985                         // generate a color array for the fog pass
9986                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9987                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9988                         RSurf_DrawBatch();
9989                         break;
9990                 default:
9991                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9992                 }
9993         }
9994         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9995         {
9996                 GL_DepthFunc(GL_LEQUAL);
9997                 GL_AlphaTest(false);
9998         }
9999 }
10000
10001 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10002 {
10003         // OpenGL 1.1 - crusty old voodoo path
10004         qboolean applyfog;
10005         int layerindex;
10006         const texturelayer_t *layer;
10007         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);
10008         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10009
10010         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10011         {
10012                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10013                 {
10014                         if (layerindex == 0)
10015                                 GL_AlphaTest(true);
10016                         else
10017                         {
10018                                 GL_AlphaTest(false);
10019                                 GL_DepthFunc(GL_EQUAL);
10020                         }
10021                 }
10022                 GL_DepthMask(layer->depthmask && writedepth);
10023                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10024                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10025                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10026                 switch (layer->type)
10027                 {
10028                 case TEXTURELAYERTYPE_LITTEXTURE:
10029                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10030                         {
10031                                 // two-pass lit texture with 2x rgbscale
10032                                 // first the lightmap pass
10033                                 R_Mesh_TexBind(0, r_texture_white);
10034                                 R_Mesh_TexMatrix(0, NULL);
10035                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10036                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10037                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10038                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10039                                 else if (FAKELIGHT_ENABLED)
10040                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10041                                 else if (rsurface.uselightmaptexture)
10042                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10043                                 else
10044                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10045                                 // then apply the texture to it
10046                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10047                                 R_Mesh_TexBind(0, layer->texture);
10048                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10049                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10050                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10051                                 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);
10052                         }
10053                         else
10054                         {
10055                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10056                                 R_Mesh_TexBind(0, layer->texture);
10057                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10058                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10059                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10060                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10061                                         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);
10062                                 else
10063                                         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);
10064                         }
10065                         break;
10066                 case TEXTURELAYERTYPE_TEXTURE:
10067                         // singletexture unlit texture with transparency support
10068                         R_Mesh_TexBind(0, layer->texture);
10069                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10070                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10071                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10072                         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);
10073                         break;
10074                 case TEXTURELAYERTYPE_FOG:
10075                         // singletexture fogging
10076                         if (layer->texture)
10077                         {
10078                                 R_Mesh_TexBind(0, layer->texture);
10079                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10080                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10081                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10082                         }
10083                         else
10084                         {
10085                                 R_Mesh_TexBind(0, 0);
10086                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10087                         }
10088                         // generate a color array for the fog pass
10089                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10090                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10091                         RSurf_DrawBatch();
10092                         break;
10093                 default:
10094                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10095                 }
10096         }
10097         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10098         {
10099                 GL_DepthFunc(GL_LEQUAL);
10100                 GL_AlphaTest(false);
10101         }
10102 }
10103
10104 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10105 {
10106         int vi;
10107         int j;
10108         r_vertexgeneric_t *batchvertex;
10109         float c[4];
10110
10111 //      R_Mesh_ResetTextureState();
10112         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10113
10114         if(rsurface.texture && rsurface.texture->currentskinframe)
10115         {
10116                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10117                 c[3] *= rsurface.texture->currentalpha;
10118         }
10119         else
10120         {
10121                 c[0] = 1;
10122                 c[1] = 0;
10123                 c[2] = 1;
10124                 c[3] = 1;
10125         }
10126
10127         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10128         {
10129                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10130                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10131                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10132         }
10133
10134         // brighten it up (as texture value 127 means "unlit")
10135         c[0] *= 2 * r_refdef.view.colorscale;
10136         c[1] *= 2 * r_refdef.view.colorscale;
10137         c[2] *= 2 * r_refdef.view.colorscale;
10138
10139         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10140                 c[3] *= r_wateralpha.value;
10141
10142         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10143         {
10144                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10145                 GL_DepthMask(false);
10146         }
10147         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10148         {
10149                 GL_BlendFunc(GL_ONE, GL_ONE);
10150                 GL_DepthMask(false);
10151         }
10152         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10153         {
10154                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10155                 GL_DepthMask(false);
10156         }
10157         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10158         {
10159                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10160                 GL_DepthMask(false);
10161         }
10162         else
10163         {
10164                 GL_BlendFunc(GL_ONE, GL_ZERO);
10165                 GL_DepthMask(writedepth);
10166         }
10167
10168         if (r_showsurfaces.integer == 3)
10169         {
10170                 rsurface.passcolor4f = NULL;
10171
10172                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10173                 {
10174                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10175
10176                         rsurface.passcolor4f = NULL;
10177                         rsurface.passcolor4f_vertexbuffer = 0;
10178                         rsurface.passcolor4f_bufferoffset = 0;
10179                 }
10180                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10181                 {
10182                         qboolean applycolor = true;
10183                         float one = 1.0;
10184
10185                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10186
10187                         r_refdef.lightmapintensity = 1;
10188                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10189                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10190                 }
10191                 else if (FAKELIGHT_ENABLED)
10192                 {
10193                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10194
10195                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10196                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10197                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10198                 }
10199                 else
10200                 {
10201                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10202
10203                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10204                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10205                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10206                 }
10207
10208                 if(!rsurface.passcolor4f)
10209                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10210
10211                 RSurf_DrawBatch_GL11_ApplyAmbient();
10212                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10213                 if(r_refdef.fogenabled)
10214                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10215                 RSurf_DrawBatch_GL11_ClampColor();
10216
10217                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10218                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10219                 RSurf_DrawBatch();
10220         }
10221         else if (!r_refdef.view.showdebug)
10222         {
10223                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10224                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10225                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10226                 {
10227                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10228                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10229                 }
10230                 R_Mesh_PrepareVertices_Generic_Unlock();
10231                 RSurf_DrawBatch();
10232         }
10233         else if (r_showsurfaces.integer == 4)
10234         {
10235                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10236                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10237                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10238                 {
10239                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10240                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10241                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10242                 }
10243                 R_Mesh_PrepareVertices_Generic_Unlock();
10244                 RSurf_DrawBatch();
10245         }
10246         else if (r_showsurfaces.integer == 2)
10247         {
10248                 const int *e;
10249                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10250                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10251                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10252                 {
10253                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10254                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10255                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10256                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10257                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10258                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10259                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10260                 }
10261                 R_Mesh_PrepareVertices_Generic_Unlock();
10262                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10263         }
10264         else
10265         {
10266                 int texturesurfaceindex;
10267                 int k;
10268                 const msurface_t *surface;
10269                 float surfacecolor4f[4];
10270                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10271                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10272                 vi = 0;
10273                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10274                 {
10275                         surface = texturesurfacelist[texturesurfaceindex];
10276                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10277                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10278                         for (j = 0;j < surface->num_vertices;j++)
10279                         {
10280                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10281                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10282                                 vi++;
10283                         }
10284                 }
10285                 R_Mesh_PrepareVertices_Generic_Unlock();
10286                 RSurf_DrawBatch();
10287         }
10288 }
10289
10290 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10291 {
10292         CHECKGLERROR
10293         RSurf_SetupDepthAndCulling();
10294         if (r_showsurfaces.integer)
10295         {
10296                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10297                 return;
10298         }
10299         switch (vid.renderpath)
10300         {
10301         case RENDERPATH_GL20:
10302         case RENDERPATH_D3D9:
10303         case RENDERPATH_D3D10:
10304         case RENDERPATH_D3D11:
10305         case RENDERPATH_SOFT:
10306         case RENDERPATH_GLES2:
10307                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10308                 break;
10309         case RENDERPATH_GL13:
10310         case RENDERPATH_GLES1:
10311                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10312                 break;
10313         case RENDERPATH_GL11:
10314                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10315                 break;
10316         }
10317         CHECKGLERROR
10318 }
10319
10320 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10321 {
10322         CHECKGLERROR
10323         RSurf_SetupDepthAndCulling();
10324         if (r_showsurfaces.integer)
10325         {
10326                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10327                 return;
10328         }
10329         switch (vid.renderpath)
10330         {
10331         case RENDERPATH_GL20:
10332         case RENDERPATH_D3D9:
10333         case RENDERPATH_D3D10:
10334         case RENDERPATH_D3D11:
10335         case RENDERPATH_SOFT:
10336         case RENDERPATH_GLES2:
10337                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10338                 break;
10339         case RENDERPATH_GL13:
10340         case RENDERPATH_GLES1:
10341                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10342                 break;
10343         case RENDERPATH_GL11:
10344                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10345                 break;
10346         }
10347         CHECKGLERROR
10348 }
10349
10350 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10351 {
10352         int i, j;
10353         int texturenumsurfaces, endsurface;
10354         texture_t *texture;
10355         const msurface_t *surface;
10356         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10357
10358         // if the model is static it doesn't matter what value we give for
10359         // wantnormals and wanttangents, so this logic uses only rules applicable
10360         // to a model, knowing that they are meaningless otherwise
10361         if (ent == r_refdef.scene.worldentity)
10362                 RSurf_ActiveWorldEntity();
10363         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10364                 RSurf_ActiveModelEntity(ent, false, false, false);
10365         else
10366         {
10367                 switch (vid.renderpath)
10368                 {
10369                 case RENDERPATH_GL20:
10370                 case RENDERPATH_D3D9:
10371                 case RENDERPATH_D3D10:
10372                 case RENDERPATH_D3D11:
10373                 case RENDERPATH_SOFT:
10374                 case RENDERPATH_GLES2:
10375                         RSurf_ActiveModelEntity(ent, true, true, false);
10376                         break;
10377                 case RENDERPATH_GL11:
10378                 case RENDERPATH_GL13:
10379                 case RENDERPATH_GLES1:
10380                         RSurf_ActiveModelEntity(ent, true, false, false);
10381                         break;
10382                 }
10383         }
10384
10385         if (r_transparentdepthmasking.integer)
10386         {
10387                 qboolean setup = false;
10388                 for (i = 0;i < numsurfaces;i = j)
10389                 {
10390                         j = i + 1;
10391                         surface = rsurface.modelsurfaces + surfacelist[i];
10392                         texture = surface->texture;
10393                         rsurface.texture = R_GetCurrentTexture(texture);
10394                         rsurface.lightmaptexture = NULL;
10395                         rsurface.deluxemaptexture = NULL;
10396                         rsurface.uselightmaptexture = false;
10397                         // scan ahead until we find a different texture
10398                         endsurface = min(i + 1024, numsurfaces);
10399                         texturenumsurfaces = 0;
10400                         texturesurfacelist[texturenumsurfaces++] = surface;
10401                         for (;j < endsurface;j++)
10402                         {
10403                                 surface = rsurface.modelsurfaces + surfacelist[j];
10404                                 if (texture != surface->texture)
10405                                         break;
10406                                 texturesurfacelist[texturenumsurfaces++] = surface;
10407                         }
10408                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10409                                 continue;
10410                         // render the range of surfaces as depth
10411                         if (!setup)
10412                         {
10413                                 setup = true;
10414                                 GL_ColorMask(0,0,0,0);
10415                                 GL_Color(1,1,1,1);
10416                                 GL_DepthTest(true);
10417                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10418                                 GL_DepthMask(true);
10419 //                              R_Mesh_ResetTextureState();
10420                                 R_SetupShader_DepthOrShadow(false);
10421                         }
10422                         RSurf_SetupDepthAndCulling();
10423                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10424                         if (rsurface.batchvertex3fbuffer)
10425                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10426                         else
10427                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10428                         RSurf_DrawBatch();
10429                 }
10430                 if (setup)
10431                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10432         }
10433
10434         for (i = 0;i < numsurfaces;i = j)
10435         {
10436                 j = i + 1;
10437                 surface = rsurface.modelsurfaces + surfacelist[i];
10438                 texture = surface->texture;
10439                 rsurface.texture = R_GetCurrentTexture(texture);
10440                 // scan ahead until we find a different texture
10441                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10442                 texturenumsurfaces = 0;
10443                 texturesurfacelist[texturenumsurfaces++] = surface;
10444                 if(FAKELIGHT_ENABLED)
10445                 {
10446                         rsurface.lightmaptexture = NULL;
10447                         rsurface.deluxemaptexture = NULL;
10448                         rsurface.uselightmaptexture = false;
10449                         for (;j < endsurface;j++)
10450                         {
10451                                 surface = rsurface.modelsurfaces + surfacelist[j];
10452                                 if (texture != surface->texture)
10453                                         break;
10454                                 texturesurfacelist[texturenumsurfaces++] = surface;
10455                         }
10456                 }
10457                 else
10458                 {
10459                         rsurface.lightmaptexture = surface->lightmaptexture;
10460                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10461                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10462                         for (;j < endsurface;j++)
10463                         {
10464                                 surface = rsurface.modelsurfaces + surfacelist[j];
10465                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10466                                         break;
10467                                 texturesurfacelist[texturenumsurfaces++] = surface;
10468                         }
10469                 }
10470                 // render the range of surfaces
10471                 if (ent == r_refdef.scene.worldentity)
10472                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10473                 else
10474                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10475         }
10476         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10477 }
10478
10479 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10480 {
10481         // transparent surfaces get pushed off into the transparent queue
10482         int surfacelistindex;
10483         const msurface_t *surface;
10484         vec3_t tempcenter, center;
10485         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10486         {
10487                 surface = texturesurfacelist[surfacelistindex];
10488                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10489                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10490                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10491                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10492                 if (queueentity->transparent_offset) // transparent offset
10493                 {
10494                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10495                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10496                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10497                 }
10498                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10499         }
10500 }
10501
10502 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10503 {
10504         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10505                 return;
10506         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10507                 return;
10508         RSurf_SetupDepthAndCulling();
10509         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10510         if (rsurface.batchvertex3fbuffer)
10511                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10512         else
10513                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10514         RSurf_DrawBatch();
10515 }
10516
10517 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10518 {
10519         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10520         CHECKGLERROR
10521         if (depthonly)
10522                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10523         else if (prepass)
10524         {
10525                 if (!rsurface.texture->currentnumlayers)
10526                         return;
10527                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10528                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10529                 else
10530                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10531         }
10532         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10533                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10534         else if (!rsurface.texture->currentnumlayers)
10535                 return;
10536         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10537         {
10538                 // in the deferred case, transparent surfaces were queued during prepass
10539                 if (!r_shadow_usingdeferredprepass)
10540                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10541         }
10542         else
10543         {
10544                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10545                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10546         }
10547         CHECKGLERROR
10548 }
10549
10550 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10551 {
10552         int i, j;
10553         texture_t *texture;
10554         R_FrameData_SetMark();
10555         // break the surface list down into batches by texture and use of lightmapping
10556         for (i = 0;i < numsurfaces;i = j)
10557         {
10558                 j = i + 1;
10559                 // texture is the base texture pointer, rsurface.texture is the
10560                 // current frame/skin the texture is directing us to use (for example
10561                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10562                 // use skin 1 instead)
10563                 texture = surfacelist[i]->texture;
10564                 rsurface.texture = R_GetCurrentTexture(texture);
10565                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10566                 {
10567                         // if this texture is not the kind we want, skip ahead to the next one
10568                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10569                                 ;
10570                         continue;
10571                 }
10572                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10573                 {
10574                         rsurface.lightmaptexture = NULL;
10575                         rsurface.deluxemaptexture = NULL;
10576                         rsurface.uselightmaptexture = false;
10577                         // simply scan ahead until we find a different texture or lightmap state
10578                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10579                                 ;
10580                 }
10581                 else
10582                 {
10583                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10584                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10585                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10586                         // simply scan ahead until we find a different texture or lightmap state
10587                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10588                                 ;
10589                 }
10590                 // render the range of surfaces
10591                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10592         }
10593         R_FrameData_ReturnToMark();
10594 }
10595
10596 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10597 {
10598         CHECKGLERROR
10599         if (depthonly)
10600                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10601         else if (prepass)
10602         {
10603                 if (!rsurface.texture->currentnumlayers)
10604                         return;
10605                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10606                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10607                 else
10608                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10609         }
10610         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10611                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10612         else if (!rsurface.texture->currentnumlayers)
10613                 return;
10614         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10615         {
10616                 // in the deferred case, transparent surfaces were queued during prepass
10617                 if (!r_shadow_usingdeferredprepass)
10618                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10619         }
10620         else
10621         {
10622                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10623                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10624         }
10625         CHECKGLERROR
10626 }
10627
10628 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10629 {
10630         int i, j;
10631         texture_t *texture;
10632         R_FrameData_SetMark();
10633         // break the surface list down into batches by texture and use of lightmapping
10634         for (i = 0;i < numsurfaces;i = j)
10635         {
10636                 j = i + 1;
10637                 // texture is the base texture pointer, rsurface.texture is the
10638                 // current frame/skin the texture is directing us to use (for example
10639                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10640                 // use skin 1 instead)
10641                 texture = surfacelist[i]->texture;
10642                 rsurface.texture = R_GetCurrentTexture(texture);
10643                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10644                 {
10645                         // if this texture is not the kind we want, skip ahead to the next one
10646                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10647                                 ;
10648                         continue;
10649                 }
10650                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10651                 {
10652                         rsurface.lightmaptexture = NULL;
10653                         rsurface.deluxemaptexture = NULL;
10654                         rsurface.uselightmaptexture = false;
10655                         // simply scan ahead until we find a different texture or lightmap state
10656                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10657                                 ;
10658                 }
10659                 else
10660                 {
10661                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10662                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10663                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10664                         // simply scan ahead until we find a different texture or lightmap state
10665                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10666                                 ;
10667                 }
10668                 // render the range of surfaces
10669                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10670         }
10671         R_FrameData_ReturnToMark();
10672 }
10673
10674 float locboxvertex3f[6*4*3] =
10675 {
10676         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10677         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10678         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10679         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10680         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10681         1,0,0, 0,0,0, 0,1,0, 1,1,0
10682 };
10683
10684 unsigned short locboxelements[6*2*3] =
10685 {
10686          0, 1, 2, 0, 2, 3,
10687          4, 5, 6, 4, 6, 7,
10688          8, 9,10, 8,10,11,
10689         12,13,14, 12,14,15,
10690         16,17,18, 16,18,19,
10691         20,21,22, 20,22,23
10692 };
10693
10694 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10695 {
10696         int i, j;
10697         cl_locnode_t *loc = (cl_locnode_t *)ent;
10698         vec3_t mins, size;
10699         float vertex3f[6*4*3];
10700         CHECKGLERROR
10701         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10702         GL_DepthMask(false);
10703         GL_DepthRange(0, 1);
10704         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10705         GL_DepthTest(true);
10706         GL_CullFace(GL_NONE);
10707         R_EntityMatrix(&identitymatrix);
10708
10709 //      R_Mesh_ResetTextureState();
10710
10711         i = surfacelist[0];
10712         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10713                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10714                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10715                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10716
10717         if (VectorCompare(loc->mins, loc->maxs))
10718         {
10719                 VectorSet(size, 2, 2, 2);
10720                 VectorMA(loc->mins, -0.5f, size, mins);
10721         }
10722         else
10723         {
10724                 VectorCopy(loc->mins, mins);
10725                 VectorSubtract(loc->maxs, loc->mins, size);
10726         }
10727
10728         for (i = 0;i < 6*4*3;)
10729                 for (j = 0;j < 3;j++, i++)
10730                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10731
10732         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10733         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10734         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10735 }
10736
10737 void R_DrawLocs(void)
10738 {
10739         int index;
10740         cl_locnode_t *loc, *nearestloc;
10741         vec3_t center;
10742         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10743         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10744         {
10745                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10746                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10747         }
10748 }
10749
10750 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10751 {
10752         if (decalsystem->decals)
10753                 Mem_Free(decalsystem->decals);
10754         memset(decalsystem, 0, sizeof(*decalsystem));
10755 }
10756
10757 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)
10758 {
10759         tridecal_t *decal;
10760         tridecal_t *decals;
10761         int i;
10762
10763         // expand or initialize the system
10764         if (decalsystem->maxdecals <= decalsystem->numdecals)
10765         {
10766                 decalsystem_t old = *decalsystem;
10767                 qboolean useshortelements;
10768                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10769                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10770                 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)));
10771                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10772                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10773                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10774                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10775                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10776                 if (decalsystem->numdecals)
10777                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10778                 if (old.decals)
10779                         Mem_Free(old.decals);
10780                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10781                         decalsystem->element3i[i] = i;
10782                 if (useshortelements)
10783                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10784                                 decalsystem->element3s[i] = i;
10785         }
10786
10787         // grab a decal and search for another free slot for the next one
10788         decals = decalsystem->decals;
10789         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10790         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10791                 ;
10792         decalsystem->freedecal = i;
10793         if (decalsystem->numdecals <= i)
10794                 decalsystem->numdecals = i + 1;
10795
10796         // initialize the decal
10797         decal->lived = 0;
10798         decal->triangleindex = triangleindex;
10799         decal->surfaceindex = surfaceindex;
10800         decal->decalsequence = decalsequence;
10801         decal->color4f[0][0] = c0[0];
10802         decal->color4f[0][1] = c0[1];
10803         decal->color4f[0][2] = c0[2];
10804         decal->color4f[0][3] = 1;
10805         decal->color4f[1][0] = c1[0];
10806         decal->color4f[1][1] = c1[1];
10807         decal->color4f[1][2] = c1[2];
10808         decal->color4f[1][3] = 1;
10809         decal->color4f[2][0] = c2[0];
10810         decal->color4f[2][1] = c2[1];
10811         decal->color4f[2][2] = c2[2];
10812         decal->color4f[2][3] = 1;
10813         decal->vertex3f[0][0] = v0[0];
10814         decal->vertex3f[0][1] = v0[1];
10815         decal->vertex3f[0][2] = v0[2];
10816         decal->vertex3f[1][0] = v1[0];
10817         decal->vertex3f[1][1] = v1[1];
10818         decal->vertex3f[1][2] = v1[2];
10819         decal->vertex3f[2][0] = v2[0];
10820         decal->vertex3f[2][1] = v2[1];
10821         decal->vertex3f[2][2] = v2[2];
10822         decal->texcoord2f[0][0] = t0[0];
10823         decal->texcoord2f[0][1] = t0[1];
10824         decal->texcoord2f[1][0] = t1[0];
10825         decal->texcoord2f[1][1] = t1[1];
10826         decal->texcoord2f[2][0] = t2[0];
10827         decal->texcoord2f[2][1] = t2[1];
10828         TriangleNormal(v0, v1, v2, decal->plane);
10829         VectorNormalize(decal->plane);
10830         decal->plane[3] = DotProduct(v0, decal->plane);
10831 }
10832
10833 extern cvar_t cl_decals_bias;
10834 extern cvar_t cl_decals_models;
10835 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10836 // baseparms, parms, temps
10837 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)
10838 {
10839         int cornerindex;
10840         int index;
10841         float v[9][3];
10842         const float *vertex3f;
10843         const float *normal3f;
10844         int numpoints;
10845         float points[2][9][3];
10846         float temp[3];
10847         float tc[9][2];
10848         float f;
10849         float c[9][4];
10850         const int *e;
10851
10852         e = rsurface.modelelement3i + 3*triangleindex;
10853
10854         vertex3f = rsurface.modelvertex3f;
10855         normal3f = rsurface.modelnormal3f;
10856
10857         if (normal3f)
10858         {
10859                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10860                 {
10861                         index = 3*e[cornerindex];
10862                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10863                 }
10864         }
10865         else
10866         {
10867                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10868                 {
10869                         index = 3*e[cornerindex];
10870                         VectorCopy(vertex3f + index, v[cornerindex]);
10871                 }
10872         }
10873
10874         // cull backfaces
10875         //TriangleNormal(v[0], v[1], v[2], normal);
10876         //if (DotProduct(normal, localnormal) < 0.0f)
10877         //      continue;
10878         // clip by each of the box planes formed from the projection matrix
10879         // if anything survives, we emit the decal
10880         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]);
10881         if (numpoints < 3)
10882                 return;
10883         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]);
10884         if (numpoints < 3)
10885                 return;
10886         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]);
10887         if (numpoints < 3)
10888                 return;
10889         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]);
10890         if (numpoints < 3)
10891                 return;
10892         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]);
10893         if (numpoints < 3)
10894                 return;
10895         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]);
10896         if (numpoints < 3)
10897                 return;
10898         // some part of the triangle survived, so we have to accept it...
10899         if (dynamic)
10900         {
10901                 // dynamic always uses the original triangle
10902                 numpoints = 3;
10903                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10904                 {
10905                         index = 3*e[cornerindex];
10906                         VectorCopy(vertex3f + index, v[cornerindex]);
10907                 }
10908         }
10909         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10910         {
10911                 // convert vertex positions to texcoords
10912                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10913                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10914                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10915                 // calculate distance fade from the projection origin
10916                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10917                 f = bound(0.0f, f, 1.0f);
10918                 c[cornerindex][0] = r * f;
10919                 c[cornerindex][1] = g * f;
10920                 c[cornerindex][2] = b * f;
10921                 c[cornerindex][3] = 1.0f;
10922                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10923         }
10924         if (dynamic)
10925                 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);
10926         else
10927                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10928                         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);
10929 }
10930 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)
10931 {
10932         matrix4x4_t projection;
10933         decalsystem_t *decalsystem;
10934         qboolean dynamic;
10935         dp_model_t *model;
10936         const msurface_t *surface;
10937         const msurface_t *surfaces;
10938         const int *surfacelist;
10939         const texture_t *texture;
10940         int numtriangles;
10941         int numsurfacelist;
10942         int surfacelistindex;
10943         int surfaceindex;
10944         int triangleindex;
10945         float localorigin[3];
10946         float localnormal[3];
10947         float localmins[3];
10948         float localmaxs[3];
10949         float localsize;
10950         //float normal[3];
10951         float planes[6][4];
10952         float angles[3];
10953         bih_t *bih;
10954         int bih_triangles_count;
10955         int bih_triangles[256];
10956         int bih_surfaces[256];
10957
10958         decalsystem = &ent->decalsystem;
10959         model = ent->model;
10960         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10961         {
10962                 R_DecalSystem_Reset(&ent->decalsystem);
10963                 return;
10964         }
10965
10966         if (!model->brush.data_leafs && !cl_decals_models.integer)
10967         {
10968                 if (decalsystem->model)
10969                         R_DecalSystem_Reset(decalsystem);
10970                 return;
10971         }
10972
10973         if (decalsystem->model != model)
10974                 R_DecalSystem_Reset(decalsystem);
10975         decalsystem->model = model;
10976
10977         RSurf_ActiveModelEntity(ent, true, false, false);
10978
10979         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10980         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10981         VectorNormalize(localnormal);
10982         localsize = worldsize*rsurface.inversematrixscale;
10983         localmins[0] = localorigin[0] - localsize;
10984         localmins[1] = localorigin[1] - localsize;
10985         localmins[2] = localorigin[2] - localsize;
10986         localmaxs[0] = localorigin[0] + localsize;
10987         localmaxs[1] = localorigin[1] + localsize;
10988         localmaxs[2] = localorigin[2] + localsize;
10989
10990         //VectorCopy(localnormal, planes[4]);
10991         //VectorVectors(planes[4], planes[2], planes[0]);
10992         AnglesFromVectors(angles, localnormal, NULL, false);
10993         AngleVectors(angles, planes[0], planes[2], planes[4]);
10994         VectorNegate(planes[0], planes[1]);
10995         VectorNegate(planes[2], planes[3]);
10996         VectorNegate(planes[4], planes[5]);
10997         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10998         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10999         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11000         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11001         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11002         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11003
11004 #if 1
11005 // works
11006 {
11007         matrix4x4_t forwardprojection;
11008         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11009         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11010 }
11011 #else
11012 // broken
11013 {
11014         float projectionvector[4][3];
11015         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11016         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11017         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11018         projectionvector[0][0] = planes[0][0] * ilocalsize;
11019         projectionvector[0][1] = planes[1][0] * ilocalsize;
11020         projectionvector[0][2] = planes[2][0] * ilocalsize;
11021         projectionvector[1][0] = planes[0][1] * ilocalsize;
11022         projectionvector[1][1] = planes[1][1] * ilocalsize;
11023         projectionvector[1][2] = planes[2][1] * ilocalsize;
11024         projectionvector[2][0] = planes[0][2] * ilocalsize;
11025         projectionvector[2][1] = planes[1][2] * ilocalsize;
11026         projectionvector[2][2] = planes[2][2] * ilocalsize;
11027         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11028         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11029         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11030         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11031 }
11032 #endif
11033
11034         dynamic = model->surfmesh.isanimated;
11035         numsurfacelist = model->nummodelsurfaces;
11036         surfacelist = model->sortedmodelsurfaces;
11037         surfaces = model->data_surfaces;
11038
11039         bih = NULL;
11040         bih_triangles_count = -1;
11041         if(!dynamic)
11042         {
11043                 if(model->render_bih.numleafs)
11044                         bih = &model->render_bih;
11045                 else if(model->collision_bih.numleafs)
11046                         bih = &model->collision_bih;
11047         }
11048         if(bih)
11049                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11050         if(bih_triangles_count == 0)
11051                 return;
11052         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11053                 return;
11054         if(bih_triangles_count > 0)
11055         {
11056                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11057                 {
11058                         surfaceindex = bih_surfaces[triangleindex];
11059                         surface = surfaces + surfaceindex;
11060                         texture = surface->texture;
11061                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11062                                 continue;
11063                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11064                                 continue;
11065                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11066                 }
11067         }
11068         else
11069         {
11070                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11071                 {
11072                         surfaceindex = surfacelist[surfacelistindex];
11073                         surface = surfaces + surfaceindex;
11074                         // check cull box first because it rejects more than any other check
11075                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11076                                 continue;
11077                         // skip transparent surfaces
11078                         texture = surface->texture;
11079                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11080                                 continue;
11081                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11082                                 continue;
11083                         numtriangles = surface->num_triangles;
11084                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11085                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11086                 }
11087         }
11088 }
11089
11090 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11091 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)
11092 {
11093         int renderentityindex;
11094         float worldmins[3];
11095         float worldmaxs[3];
11096         entity_render_t *ent;
11097
11098         if (!cl_decals_newsystem.integer)
11099                 return;
11100
11101         worldmins[0] = worldorigin[0] - worldsize;
11102         worldmins[1] = worldorigin[1] - worldsize;
11103         worldmins[2] = worldorigin[2] - worldsize;
11104         worldmaxs[0] = worldorigin[0] + worldsize;
11105         worldmaxs[1] = worldorigin[1] + worldsize;
11106         worldmaxs[2] = worldorigin[2] + worldsize;
11107
11108         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11109
11110         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11111         {
11112                 ent = r_refdef.scene.entities[renderentityindex];
11113                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11114                         continue;
11115
11116                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11117         }
11118 }
11119
11120 typedef struct r_decalsystem_splatqueue_s
11121 {
11122         vec3_t worldorigin;
11123         vec3_t worldnormal;
11124         float color[4];
11125         float tcrange[4];
11126         float worldsize;
11127         int decalsequence;
11128 }
11129 r_decalsystem_splatqueue_t;
11130
11131 int r_decalsystem_numqueued = 0;
11132 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11133
11134 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)
11135 {
11136         r_decalsystem_splatqueue_t *queue;
11137
11138         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11139                 return;
11140
11141         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11142         VectorCopy(worldorigin, queue->worldorigin);
11143         VectorCopy(worldnormal, queue->worldnormal);
11144         Vector4Set(queue->color, r, g, b, a);
11145         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11146         queue->worldsize = worldsize;
11147         queue->decalsequence = cl.decalsequence++;
11148 }
11149
11150 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11151 {
11152         int i;
11153         r_decalsystem_splatqueue_t *queue;
11154
11155         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11156                 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);
11157         r_decalsystem_numqueued = 0;
11158 }
11159
11160 extern cvar_t cl_decals_max;
11161 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11162 {
11163         int i;
11164         decalsystem_t *decalsystem = &ent->decalsystem;
11165         int numdecals;
11166         int killsequence;
11167         tridecal_t *decal;
11168         float frametime;
11169         float lifetime;
11170
11171         if (!decalsystem->numdecals)
11172                 return;
11173
11174         if (r_showsurfaces.integer)
11175                 return;
11176
11177         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11178         {
11179                 R_DecalSystem_Reset(decalsystem);
11180                 return;
11181         }
11182
11183         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11184         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11185
11186         if (decalsystem->lastupdatetime)
11187                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11188         else
11189                 frametime = 0;
11190         decalsystem->lastupdatetime = r_refdef.scene.time;
11191         decal = decalsystem->decals;
11192         numdecals = decalsystem->numdecals;
11193
11194         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11195         {
11196                 if (decal->color4f[0][3])
11197                 {
11198                         decal->lived += frametime;
11199                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11200                         {
11201                                 memset(decal, 0, sizeof(*decal));
11202                                 if (decalsystem->freedecal > i)
11203                                         decalsystem->freedecal = i;
11204                         }
11205                 }
11206         }
11207         decal = decalsystem->decals;
11208         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11209                 numdecals--;
11210
11211         // collapse the array by shuffling the tail decals into the gaps
11212         for (;;)
11213         {
11214                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11215                         decalsystem->freedecal++;
11216                 if (decalsystem->freedecal == numdecals)
11217                         break;
11218                 decal[decalsystem->freedecal] = decal[--numdecals];
11219         }
11220
11221         decalsystem->numdecals = numdecals;
11222
11223         if (numdecals <= 0)
11224         {
11225                 // if there are no decals left, reset decalsystem
11226                 R_DecalSystem_Reset(decalsystem);
11227         }
11228 }
11229
11230 extern skinframe_t *decalskinframe;
11231 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11232 {
11233         int i;
11234         decalsystem_t *decalsystem = &ent->decalsystem;
11235         int numdecals;
11236         tridecal_t *decal;
11237         float faderate;
11238         float alpha;
11239         float *v3f;
11240         float *c4f;
11241         float *t2f;
11242         const int *e;
11243         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11244         int numtris = 0;
11245
11246         numdecals = decalsystem->numdecals;
11247         if (!numdecals)
11248                 return;
11249
11250         if (r_showsurfaces.integer)
11251                 return;
11252
11253         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11254         {
11255                 R_DecalSystem_Reset(decalsystem);
11256                 return;
11257         }
11258
11259         // if the model is static it doesn't matter what value we give for
11260         // wantnormals and wanttangents, so this logic uses only rules applicable
11261         // to a model, knowing that they are meaningless otherwise
11262         if (ent == r_refdef.scene.worldentity)
11263                 RSurf_ActiveWorldEntity();
11264         else
11265                 RSurf_ActiveModelEntity(ent, false, false, false);
11266
11267         decalsystem->lastupdatetime = r_refdef.scene.time;
11268         decal = decalsystem->decals;
11269
11270         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11271
11272         // update vertex positions for animated models
11273         v3f = decalsystem->vertex3f;
11274         c4f = decalsystem->color4f;
11275         t2f = decalsystem->texcoord2f;
11276         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11277         {
11278                 if (!decal->color4f[0][3])
11279                         continue;
11280
11281                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11282                         continue;
11283
11284                 // skip backfaces
11285                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11286                         continue;
11287
11288                 // update color values for fading decals
11289                 if (decal->lived >= cl_decals_time.value)
11290                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11291                 else
11292                         alpha = 1.0f;
11293
11294                 c4f[ 0] = decal->color4f[0][0] * alpha;
11295                 c4f[ 1] = decal->color4f[0][1] * alpha;
11296                 c4f[ 2] = decal->color4f[0][2] * alpha;
11297                 c4f[ 3] = 1;
11298                 c4f[ 4] = decal->color4f[1][0] * alpha;
11299                 c4f[ 5] = decal->color4f[1][1] * alpha;
11300                 c4f[ 6] = decal->color4f[1][2] * alpha;
11301                 c4f[ 7] = 1;
11302                 c4f[ 8] = decal->color4f[2][0] * alpha;
11303                 c4f[ 9] = decal->color4f[2][1] * alpha;
11304                 c4f[10] = decal->color4f[2][2] * alpha;
11305                 c4f[11] = 1;
11306
11307                 t2f[0] = decal->texcoord2f[0][0];
11308                 t2f[1] = decal->texcoord2f[0][1];
11309                 t2f[2] = decal->texcoord2f[1][0];
11310                 t2f[3] = decal->texcoord2f[1][1];
11311                 t2f[4] = decal->texcoord2f[2][0];
11312                 t2f[5] = decal->texcoord2f[2][1];
11313
11314                 // update vertex positions for animated models
11315                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11316                 {
11317                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11318                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11319                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11320                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11321                 }
11322                 else
11323                 {
11324                         VectorCopy(decal->vertex3f[0], v3f);
11325                         VectorCopy(decal->vertex3f[1], v3f + 3);
11326                         VectorCopy(decal->vertex3f[2], v3f + 6);
11327                 }
11328
11329                 if (r_refdef.fogenabled)
11330                 {
11331                         alpha = RSurf_FogVertex(v3f);
11332                         VectorScale(c4f, alpha, c4f);
11333                         alpha = RSurf_FogVertex(v3f + 3);
11334                         VectorScale(c4f + 4, alpha, c4f + 4);
11335                         alpha = RSurf_FogVertex(v3f + 6);
11336                         VectorScale(c4f + 8, alpha, c4f + 8);
11337                 }
11338
11339                 v3f += 9;
11340                 c4f += 12;
11341                 t2f += 6;
11342                 numtris++;
11343         }
11344
11345         if (numtris > 0)
11346         {
11347                 r_refdef.stats.drawndecals += numtris;
11348
11349                 // now render the decals all at once
11350                 // (this assumes they all use one particle font texture!)
11351                 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);
11352 //              R_Mesh_ResetTextureState();
11353                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11354                 GL_DepthMask(false);
11355                 GL_DepthRange(0, 1);
11356                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11357                 GL_DepthTest(true);
11358                 GL_CullFace(GL_NONE);
11359                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11360                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11361                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11362         }
11363 }
11364
11365 static void R_DrawModelDecals(void)
11366 {
11367         int i, numdecals;
11368
11369         // fade faster when there are too many decals
11370         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11371         for (i = 0;i < r_refdef.scene.numentities;i++)
11372                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11373
11374         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11375         for (i = 0;i < r_refdef.scene.numentities;i++)
11376                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11377                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11378
11379         R_DecalSystem_ApplySplatEntitiesQueue();
11380
11381         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11382         for (i = 0;i < r_refdef.scene.numentities;i++)
11383                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11384
11385         r_refdef.stats.totaldecals += numdecals;
11386
11387         if (r_showsurfaces.integer)
11388                 return;
11389
11390         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11391
11392         for (i = 0;i < r_refdef.scene.numentities;i++)
11393         {
11394                 if (!r_refdef.viewcache.entityvisible[i])
11395                         continue;
11396                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11397                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11398         }
11399 }
11400
11401 extern cvar_t mod_collision_bih;
11402 void R_DrawDebugModel(void)
11403 {
11404         entity_render_t *ent = rsurface.entity;
11405         int i, j, k, l, flagsmask;
11406         const msurface_t *surface;
11407         dp_model_t *model = ent->model;
11408         vec3_t v;
11409
11410         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11411                 return;
11412
11413         if (r_showoverdraw.value > 0)
11414         {
11415                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11416                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11417                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11418                 GL_DepthTest(false);
11419                 GL_DepthMask(false);
11420                 GL_DepthRange(0, 1);
11421                 GL_BlendFunc(GL_ONE, GL_ONE);
11422                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11423                 {
11424                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11425                                 continue;
11426                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11427                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11428                         {
11429                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11430                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11431                                 if (!rsurface.texture->currentlayers->depthmask)
11432                                         GL_Color(c, 0, 0, 1.0f);
11433                                 else if (ent == r_refdef.scene.worldentity)
11434                                         GL_Color(c, c, c, 1.0f);
11435                                 else
11436                                         GL_Color(0, c, 0, 1.0f);
11437                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11438                                 RSurf_DrawBatch();
11439                         }
11440                 }
11441                 rsurface.texture = NULL;
11442         }
11443
11444         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11445
11446 //      R_Mesh_ResetTextureState();
11447         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11448         GL_DepthRange(0, 1);
11449         GL_DepthTest(!r_showdisabledepthtest.integer);
11450         GL_DepthMask(false);
11451         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11452
11453         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11454         {
11455                 int triangleindex;
11456                 int bihleafindex;
11457                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11458                 const q3mbrush_t *brush;
11459                 const bih_t *bih = &model->collision_bih;
11460                 const bih_leaf_t *bihleaf;
11461                 float vertex3f[3][3];
11462                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11463                 cullbox = false;
11464                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11465                 {
11466                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11467                                 continue;
11468                         switch (bihleaf->type)
11469                         {
11470                         case BIH_BRUSH:
11471                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11472                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11473                                 {
11474                                         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);
11475                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11476                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11477                                 }
11478                                 break;
11479                         case BIH_COLLISIONTRIANGLE:
11480                                 triangleindex = bihleaf->itemindex;
11481                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11482                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11483                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11484                                 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);
11485                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11486                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11487                                 break;
11488                         case BIH_RENDERTRIANGLE:
11489                                 triangleindex = bihleaf->itemindex;
11490                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11491                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11492                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11493                                 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);
11494                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11495                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11496                                 break;
11497                         }
11498                 }
11499         }
11500
11501         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11502
11503 #ifndef USE_GLES2
11504         if (r_showtris.integer && qglPolygonMode)
11505         {
11506                 if (r_showdisabledepthtest.integer)
11507                 {
11508                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11509                         GL_DepthMask(false);
11510                 }
11511                 else
11512                 {
11513                         GL_BlendFunc(GL_ONE, GL_ZERO);
11514                         GL_DepthMask(true);
11515                 }
11516                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11517                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11518                 {
11519                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11520                                 continue;
11521                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11522                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11523                         {
11524                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11525                                 if (!rsurface.texture->currentlayers->depthmask)
11526                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11527                                 else if (ent == r_refdef.scene.worldentity)
11528                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11529                                 else
11530                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11531                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11532                                 RSurf_DrawBatch();
11533                         }
11534                 }
11535                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11536                 rsurface.texture = NULL;
11537         }
11538
11539         if (r_shownormals.value != 0 && qglBegin)
11540         {
11541                 if (r_showdisabledepthtest.integer)
11542                 {
11543                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11544                         GL_DepthMask(false);
11545                 }
11546                 else
11547                 {
11548                         GL_BlendFunc(GL_ONE, GL_ZERO);
11549                         GL_DepthMask(true);
11550                 }
11551                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11552                 {
11553                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11554                                 continue;
11555                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11556                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11557                         {
11558                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11559                                 qglBegin(GL_LINES);
11560                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11561                                 {
11562                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11563                                         {
11564                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11565                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11566                                                 qglVertex3f(v[0], v[1], v[2]);
11567                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11568                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11569                                                 qglVertex3f(v[0], v[1], v[2]);
11570                                         }
11571                                 }
11572                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11573                                 {
11574                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11575                                         {
11576                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11577                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11578                                                 qglVertex3f(v[0], v[1], v[2]);
11579                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11580                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11581                                                 qglVertex3f(v[0], v[1], v[2]);
11582                                         }
11583                                 }
11584                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11585                                 {
11586                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11587                                         {
11588                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11589                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11590                                                 qglVertex3f(v[0], v[1], v[2]);
11591                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11592                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11593                                                 qglVertex3f(v[0], v[1], v[2]);
11594                                         }
11595                                 }
11596                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11597                                 {
11598                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11599                                         {
11600                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11601                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11602                                                 qglVertex3f(v[0], v[1], v[2]);
11603                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11604                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11605                                                 qglVertex3f(v[0], v[1], v[2]);
11606                                         }
11607                                 }
11608                                 qglEnd();
11609                                 CHECKGLERROR
11610                         }
11611                 }
11612                 rsurface.texture = NULL;
11613         }
11614 #endif
11615 }
11616
11617 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11618 int r_maxsurfacelist = 0;
11619 const msurface_t **r_surfacelist = NULL;
11620 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11621 {
11622         int i, j, endj, flagsmask;
11623         dp_model_t *model = r_refdef.scene.worldmodel;
11624         msurface_t *surfaces;
11625         unsigned char *update;
11626         int numsurfacelist = 0;
11627         if (model == NULL)
11628                 return;
11629
11630         if (r_maxsurfacelist < model->num_surfaces)
11631         {
11632                 r_maxsurfacelist = model->num_surfaces;
11633                 if (r_surfacelist)
11634                         Mem_Free((msurface_t**)r_surfacelist);
11635                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11636         }
11637
11638         RSurf_ActiveWorldEntity();
11639
11640         surfaces = model->data_surfaces;
11641         update = model->brushq1.lightmapupdateflags;
11642
11643         // update light styles on this submodel
11644         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11645         {
11646                 model_brush_lightstyleinfo_t *style;
11647                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11648                 {
11649                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11650                         {
11651                                 int *list = style->surfacelist;
11652                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11653                                 for (j = 0;j < style->numsurfaces;j++)
11654                                         update[list[j]] = true;
11655                         }
11656                 }
11657         }
11658
11659         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11660
11661         if (debug)
11662         {
11663                 R_DrawDebugModel();
11664                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11665                 return;
11666         }
11667
11668         rsurface.lightmaptexture = NULL;
11669         rsurface.deluxemaptexture = NULL;
11670         rsurface.uselightmaptexture = false;
11671         rsurface.texture = NULL;
11672         rsurface.rtlight = NULL;
11673         numsurfacelist = 0;
11674         // add visible surfaces to draw list
11675         for (i = 0;i < model->nummodelsurfaces;i++)
11676         {
11677                 j = model->sortedmodelsurfaces[i];
11678                 if (r_refdef.viewcache.world_surfacevisible[j])
11679                         r_surfacelist[numsurfacelist++] = surfaces + j;
11680         }
11681         // update lightmaps if needed
11682         if (model->brushq1.firstrender)
11683         {
11684                 model->brushq1.firstrender = false;
11685                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11686                         if (update[j])
11687                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11688         }
11689         else if (update)
11690         {
11691                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11692                         if (r_refdef.viewcache.world_surfacevisible[j])
11693                                 if (update[j])
11694                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11695         }
11696         // don't do anything if there were no surfaces
11697         if (!numsurfacelist)
11698         {
11699                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11700                 return;
11701         }
11702         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11703
11704         // add to stats if desired
11705         if (r_speeds.integer && !skysurfaces && !depthonly)
11706         {
11707                 r_refdef.stats.world_surfaces += numsurfacelist;
11708                 for (j = 0;j < numsurfacelist;j++)
11709                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11710         }
11711
11712         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11713 }
11714
11715 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11716 {
11717         int i, j, endj, flagsmask;
11718         dp_model_t *model = ent->model;
11719         msurface_t *surfaces;
11720         unsigned char *update;
11721         int numsurfacelist = 0;
11722         if (model == NULL)
11723                 return;
11724
11725         if (r_maxsurfacelist < model->num_surfaces)
11726         {
11727                 r_maxsurfacelist = model->num_surfaces;
11728                 if (r_surfacelist)
11729                         Mem_Free((msurface_t **)r_surfacelist);
11730                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11731         }
11732
11733         // if the model is static it doesn't matter what value we give for
11734         // wantnormals and wanttangents, so this logic uses only rules applicable
11735         // to a model, knowing that they are meaningless otherwise
11736         if (ent == r_refdef.scene.worldentity)
11737                 RSurf_ActiveWorldEntity();
11738         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11739                 RSurf_ActiveModelEntity(ent, false, false, false);
11740         else if (prepass)
11741                 RSurf_ActiveModelEntity(ent, true, true, true);
11742         else if (depthonly)
11743         {
11744                 switch (vid.renderpath)
11745                 {
11746                 case RENDERPATH_GL20:
11747                 case RENDERPATH_D3D9:
11748                 case RENDERPATH_D3D10:
11749                 case RENDERPATH_D3D11:
11750                 case RENDERPATH_SOFT:
11751                 case RENDERPATH_GLES2:
11752                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11753                         break;
11754                 case RENDERPATH_GL11:
11755                 case RENDERPATH_GL13:
11756                 case RENDERPATH_GLES1:
11757                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11758                         break;
11759                 }
11760         }
11761         else
11762         {
11763                 switch (vid.renderpath)
11764                 {
11765                 case RENDERPATH_GL20:
11766                 case RENDERPATH_D3D9:
11767                 case RENDERPATH_D3D10:
11768                 case RENDERPATH_D3D11:
11769                 case RENDERPATH_SOFT:
11770                 case RENDERPATH_GLES2:
11771                         RSurf_ActiveModelEntity(ent, true, true, false);
11772                         break;
11773                 case RENDERPATH_GL11:
11774                 case RENDERPATH_GL13:
11775                 case RENDERPATH_GLES1:
11776                         RSurf_ActiveModelEntity(ent, true, false, false);
11777                         break;
11778                 }
11779         }
11780
11781         surfaces = model->data_surfaces;
11782         update = model->brushq1.lightmapupdateflags;
11783
11784         // update light styles
11785         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11786         {
11787                 model_brush_lightstyleinfo_t *style;
11788                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11789                 {
11790                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11791                         {
11792                                 int *list = style->surfacelist;
11793                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11794                                 for (j = 0;j < style->numsurfaces;j++)
11795                                         update[list[j]] = true;
11796                         }
11797                 }
11798         }
11799
11800         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11801
11802         if (debug)
11803         {
11804                 R_DrawDebugModel();
11805                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11806                 return;
11807         }
11808
11809         rsurface.lightmaptexture = NULL;
11810         rsurface.deluxemaptexture = NULL;
11811         rsurface.uselightmaptexture = false;
11812         rsurface.texture = NULL;
11813         rsurface.rtlight = NULL;
11814         numsurfacelist = 0;
11815         // add visible surfaces to draw list
11816         for (i = 0;i < model->nummodelsurfaces;i++)
11817                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11818         // don't do anything if there were no surfaces
11819         if (!numsurfacelist)
11820         {
11821                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11822                 return;
11823         }
11824         // update lightmaps if needed
11825         if (update)
11826         {
11827                 int updated = 0;
11828                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11829                 {
11830                         if (update[j])
11831                         {
11832                                 updated++;
11833                                 R_BuildLightMap(ent, surfaces + j);
11834                         }
11835                 }
11836         }
11837         if (update)
11838                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11839                         if (update[j])
11840                                 R_BuildLightMap(ent, surfaces + j);
11841         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11842
11843         // add to stats if desired
11844         if (r_speeds.integer && !skysurfaces && !depthonly)
11845         {
11846                 r_refdef.stats.entities_surfaces += numsurfacelist;
11847                 for (j = 0;j < numsurfacelist;j++)
11848                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11849         }
11850
11851         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11852 }
11853
11854 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11855 {
11856         static texture_t texture;
11857         static msurface_t surface;
11858         const msurface_t *surfacelist = &surface;
11859
11860         // fake enough texture and surface state to render this geometry
11861
11862         texture.update_lastrenderframe = -1; // regenerate this texture
11863         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11864         texture.currentskinframe = skinframe;
11865         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11866         texture.offsetmapping = OFFSETMAPPING_OFF;
11867         texture.offsetscale = 1;
11868         texture.specularscalemod = 1;
11869         texture.specularpowermod = 1;
11870
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 }
11884
11885 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)
11886 {
11887         static msurface_t surface;
11888         const msurface_t *surfacelist = &surface;
11889
11890         // fake enough texture and surface state to render this geometry
11891         surface.texture = texture;
11892         surface.num_triangles = numtriangles;
11893         surface.num_firsttriangle = firsttriangle;
11894         surface.num_vertices = numvertices;
11895         surface.num_firstvertex = firstvertex;
11896
11897         // now render it
11898         rsurface.texture = R_GetCurrentTexture(surface.texture);
11899         rsurface.lightmaptexture = NULL;
11900         rsurface.deluxemaptexture = NULL;
11901         rsurface.uselightmaptexture = false;
11902         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11903 }