]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Fix typos in GPU skeletal; explain the crossproduct hack
[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 - NOTE: bad performance on multi-gpu!"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
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_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 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)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 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"};
88 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"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 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"};
91 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"};
92 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"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 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)"};
101 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)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 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."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 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."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
124 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
125 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"};
126 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"};
127 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
130 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
131 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
132 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"};
133 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
134 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
135 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
136 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
137 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138
139 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
140 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
141 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
142 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
143 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
144 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
145 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
146 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
147
148 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)"};
149 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"};
150
151 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
152 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
153 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
154
155 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
156 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"};
157 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"};
158 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
159 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
160 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"};
161 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)"};
162 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)"};
163 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
164
165 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
166 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)"};
167 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
168 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)"};
169 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
170 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)"};
171 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)"};
172 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
173 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"};
174 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."};
175 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
184
185 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)"};
186 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
187 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"};
188 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
189 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
190 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
191 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"};
192 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
193 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
194
195 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
196 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
197 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
198 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
199
200 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
201 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
202
203 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
204 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
205 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
206 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
207 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
208 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
209
210 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
211 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
212 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
213 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
214 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
215 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
217 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
218 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
219 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
220
221 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"};
222
223 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"};
224
225 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
226
227 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
228
229 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
230 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
231 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
232
233 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
234 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"};
235
236 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, requires mod_q3shader_force_terrain_alphaflag on."};
237
238 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)"};
239
240 extern cvar_t v_glslgamma;
241 extern cvar_t v_glslgamma_2d;
242
243 extern qboolean v_flipped_state;
244
245 r_framebufferstate_t r_fb;
246
247 /// shadow volume bsp struct with automatically growing nodes buffer
248 svbsp_t r_svbsp;
249
250 rtexture_t *r_texture_blanknormalmap;
251 rtexture_t *r_texture_white;
252 rtexture_t *r_texture_grey128;
253 rtexture_t *r_texture_black;
254 rtexture_t *r_texture_notexture;
255 rtexture_t *r_texture_whitecube;
256 rtexture_t *r_texture_normalizationcube;
257 rtexture_t *r_texture_fogattenuation;
258 rtexture_t *r_texture_fogheighttexture;
259 rtexture_t *r_texture_gammaramps;
260 unsigned int r_texture_gammaramps_serial;
261 //rtexture_t *r_texture_fogintensity;
262 rtexture_t *r_texture_reflectcube;
263
264 // TODO: hash lookups?
265 typedef struct cubemapinfo_s
266 {
267         char basename[64];
268         rtexture_t *texture;
269 }
270 cubemapinfo_t;
271
272 int r_texture_numcubemaps;
273 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
274
275 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
276 unsigned int r_numqueries;
277 unsigned int r_maxqueries;
278
279 typedef struct r_qwskincache_s
280 {
281         char name[MAX_QPATH];
282         skinframe_t *skinframe;
283 }
284 r_qwskincache_t;
285
286 static r_qwskincache_t *r_qwskincache;
287 static int r_qwskincache_size;
288
289 /// vertex coordinates for a quad that covers the screen exactly
290 extern const float r_screenvertex3f[12];
291 extern const float r_d3dscreenvertex3f[12];
292 const float r_screenvertex3f[12] =
293 {
294         0, 0, 0,
295         1, 0, 0,
296         1, 1, 0,
297         0, 1, 0
298 };
299 const float r_d3dscreenvertex3f[12] =
300 {
301         0, 1, 0,
302         1, 1, 0,
303         1, 0, 0,
304         0, 0, 0
305 };
306
307 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
308 {
309         int i;
310         for (i = 0;i < verts;i++)
311         {
312                 out[0] = in[0] * r;
313                 out[1] = in[1] * g;
314                 out[2] = in[2] * b;
315                 out[3] = in[3];
316                 in += 4;
317                 out += 4;
318         }
319 }
320
321 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
322 {
323         int i;
324         for (i = 0;i < verts;i++)
325         {
326                 out[0] = r;
327                 out[1] = g;
328                 out[2] = b;
329                 out[3] = a;
330                 out += 4;
331         }
332 }
333
334 // FIXME: move this to client?
335 void FOG_clear(void)
336 {
337         if (gamemode == GAME_NEHAHRA)
338         {
339                 Cvar_Set("gl_fogenable", "0");
340                 Cvar_Set("gl_fogdensity", "0.2");
341                 Cvar_Set("gl_fogred", "0.3");
342                 Cvar_Set("gl_foggreen", "0.3");
343                 Cvar_Set("gl_fogblue", "0.3");
344         }
345         r_refdef.fog_density = 0;
346         r_refdef.fog_red = 0;
347         r_refdef.fog_green = 0;
348         r_refdef.fog_blue = 0;
349         r_refdef.fog_alpha = 1;
350         r_refdef.fog_start = 0;
351         r_refdef.fog_end = 16384;
352         r_refdef.fog_height = 1<<30;
353         r_refdef.fog_fadedepth = 128;
354         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
355 }
356
357 static void R_BuildBlankTextures(void)
358 {
359         unsigned char data[4];
360         data[2] = 128; // normal X
361         data[1] = 128; // normal Y
362         data[0] = 255; // normal Z
363         data[3] = 255; // height
364         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 255;
366         data[1] = 255;
367         data[2] = 255;
368         data[3] = 255;
369         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 128;
371         data[1] = 128;
372         data[2] = 128;
373         data[3] = 255;
374         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 0;
376         data[1] = 0;
377         data[2] = 0;
378         data[3] = 255;
379         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 }
381
382 static void R_BuildNoTexture(void)
383 {
384         int x, y;
385         unsigned char pix[16][16][4];
386         // this makes a light grey/dark grey checkerboard texture
387         for (y = 0;y < 16;y++)
388         {
389                 for (x = 0;x < 16;x++)
390                 {
391                         if ((y < 8) ^ (x < 8))
392                         {
393                                 pix[y][x][0] = 128;
394                                 pix[y][x][1] = 128;
395                                 pix[y][x][2] = 128;
396                                 pix[y][x][3] = 255;
397                         }
398                         else
399                         {
400                                 pix[y][x][0] = 64;
401                                 pix[y][x][1] = 64;
402                                 pix[y][x][2] = 64;
403                                 pix[y][x][3] = 255;
404                         }
405                 }
406         }
407         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
408 }
409
410 static void R_BuildWhiteCube(void)
411 {
412         unsigned char data[6*1*1*4];
413         memset(data, 255, sizeof(data));
414         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
415 }
416
417 static void R_BuildNormalizationCube(void)
418 {
419         int x, y, side;
420         vec3_t v;
421         vec_t s, t, intensity;
422 #define NORMSIZE 64
423         unsigned char *data;
424         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
425         for (side = 0;side < 6;side++)
426         {
427                 for (y = 0;y < NORMSIZE;y++)
428                 {
429                         for (x = 0;x < NORMSIZE;x++)
430                         {
431                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
432                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
433                                 switch(side)
434                                 {
435                                 default:
436                                 case 0:
437                                         v[0] = 1;
438                                         v[1] = -t;
439                                         v[2] = -s;
440                                         break;
441                                 case 1:
442                                         v[0] = -1;
443                                         v[1] = -t;
444                                         v[2] = s;
445                                         break;
446                                 case 2:
447                                         v[0] = s;
448                                         v[1] = 1;
449                                         v[2] = t;
450                                         break;
451                                 case 3:
452                                         v[0] = s;
453                                         v[1] = -1;
454                                         v[2] = -t;
455                                         break;
456                                 case 4:
457                                         v[0] = s;
458                                         v[1] = -t;
459                                         v[2] = 1;
460                                         break;
461                                 case 5:
462                                         v[0] = -s;
463                                         v[1] = -t;
464                                         v[2] = -1;
465                                         break;
466                                 }
467                                 intensity = 127.0f / sqrt(DotProduct(v, v));
468                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
469                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
470                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
471                                 data[((side*64+y)*64+x)*4+3] = 255;
472                         }
473                 }
474         }
475         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
476         Mem_Free(data);
477 }
478
479 static void R_BuildFogTexture(void)
480 {
481         int x, b;
482 #define FOGWIDTH 256
483         unsigned char data1[FOGWIDTH][4];
484         //unsigned char data2[FOGWIDTH][4];
485         double d, r, alpha;
486
487         r_refdef.fogmasktable_start = r_refdef.fog_start;
488         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
489         r_refdef.fogmasktable_range = r_refdef.fogrange;
490         r_refdef.fogmasktable_density = r_refdef.fog_density;
491
492         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
493         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
494         {
495                 d = (x * r - r_refdef.fogmasktable_start);
496                 if(developer_extra.integer)
497                         Con_DPrintf("%f ", d);
498                 d = max(0, d);
499                 if (r_fog_exp2.integer)
500                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
501                 else
502                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
503                 if(developer_extra.integer)
504                         Con_DPrintf(" : %f ", alpha);
505                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
506                 if(developer_extra.integer)
507                         Con_DPrintf(" = %f\n", alpha);
508                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
509         }
510
511         for (x = 0;x < FOGWIDTH;x++)
512         {
513                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
514                 data1[x][0] = b;
515                 data1[x][1] = b;
516                 data1[x][2] = b;
517                 data1[x][3] = 255;
518                 //data2[x][0] = 255 - b;
519                 //data2[x][1] = 255 - b;
520                 //data2[x][2] = 255 - b;
521                 //data2[x][3] = 255;
522         }
523         if (r_texture_fogattenuation)
524         {
525                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
526                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
527         }
528         else
529         {
530                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
531                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
532         }
533 }
534
535 static void R_BuildFogHeightTexture(void)
536 {
537         unsigned char *inpixels;
538         int size;
539         int x;
540         int y;
541         int j;
542         float c[4];
543         float f;
544         inpixels = NULL;
545         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
546         if (r_refdef.fogheighttexturename[0])
547                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
548         if (!inpixels)
549         {
550                 r_refdef.fog_height_tablesize = 0;
551                 if (r_texture_fogheighttexture)
552                         R_FreeTexture(r_texture_fogheighttexture);
553                 r_texture_fogheighttexture = NULL;
554                 if (r_refdef.fog_height_table2d)
555                         Mem_Free(r_refdef.fog_height_table2d);
556                 r_refdef.fog_height_table2d = NULL;
557                 if (r_refdef.fog_height_table1d)
558                         Mem_Free(r_refdef.fog_height_table1d);
559                 r_refdef.fog_height_table1d = NULL;
560                 return;
561         }
562         size = image_width;
563         r_refdef.fog_height_tablesize = size;
564         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
565         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
566         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
567         Mem_Free(inpixels);
568         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
569         // average fog color table accounting for every fog layer between a point
570         // and the camera.  (Note: attenuation is handled separately!)
571         for (y = 0;y < size;y++)
572         {
573                 for (x = 0;x < size;x++)
574                 {
575                         Vector4Clear(c);
576                         f = 0;
577                         if (x < y)
578                         {
579                                 for (j = x;j <= y;j++)
580                                 {
581                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
582                                         f++;
583                                 }
584                         }
585                         else
586                         {
587                                 for (j = x;j >= y;j--)
588                                 {
589                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
590                                         f++;
591                                 }
592                         }
593                         f = 1.0f / f;
594                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
595                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
596                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
597                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
598                 }
599         }
600         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
601 }
602
603 //=======================================================================================================================================================
604
605 static const char *builtinshaderstring =
606 #include "shader_glsl.h"
607 ;
608
609 const char *builtinhlslshaderstring =
610 #include "shader_hlsl.h"
611 ;
612
613 char *glslshaderstring = NULL;
614 char *hlslshaderstring = NULL;
615
616 //=======================================================================================================================================================
617
618 typedef struct shaderpermutationinfo_s
619 {
620         const char *pretext;
621         const char *name;
622 }
623 shaderpermutationinfo_t;
624
625 typedef struct shadermodeinfo_s
626 {
627         const char *vertexfilename;
628         const char *geometryfilename;
629         const char *fragmentfilename;
630         const char *pretext;
631         const char *name;
632 }
633 shadermodeinfo_t;
634
635 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
636 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
637 {
638         {"#define USEDIFFUSE\n", " diffuse"},
639         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
640         {"#define USEVIEWTINT\n", " viewtint"},
641         {"#define USECOLORMAPPING\n", " colormapping"},
642         {"#define USESATURATION\n", " saturation"},
643         {"#define USEFOGINSIDE\n", " foginside"},
644         {"#define USEFOGOUTSIDE\n", " fogoutside"},
645         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
646         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
647         {"#define USEGAMMARAMPS\n", " gammaramps"},
648         {"#define USECUBEFILTER\n", " cubefilter"},
649         {"#define USEGLOW\n", " glow"},
650         {"#define USEBLOOM\n", " bloom"},
651         {"#define USESPECULAR\n", " specular"},
652         {"#define USEPOSTPROCESSING\n", " postprocessing"},
653         {"#define USEREFLECTION\n", " reflection"},
654         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
655         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
656         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
657         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
658         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
659         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
660         {"#define USEALPHAKILL\n", " alphakill"},
661         {"#define USEREFLECTCUBE\n", " reflectcube"},
662         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
663         {"#define USEBOUNCEGRID\n", " bouncegrid"},
664         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
665         {"#define USETRIPPY\n", " trippy"},
666         {"#define USEDEPTHRGB\n", " depthrgb"},
667         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
668         {"#define USESKELETAL\n", " skeletal"}
669 };
670
671 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
672 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
673 {
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
692 };
693
694 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
695 {
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
714 };
715
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
718 {
719         /// hash lookup data
720         struct r_glsl_permutation_s *hashnext;
721         unsigned int mode;
722         unsigned int permutation;
723
724         /// indicates if we have tried compiling this permutation already
725         qboolean compiled;
726         /// 0 if compilation failed
727         int program;
728         // texture units assigned to each detected uniform
729         int tex_Texture_First;
730         int tex_Texture_Second;
731         int tex_Texture_GammaRamps;
732         int tex_Texture_Normal;
733         int tex_Texture_Color;
734         int tex_Texture_Gloss;
735         int tex_Texture_Glow;
736         int tex_Texture_SecondaryNormal;
737         int tex_Texture_SecondaryColor;
738         int tex_Texture_SecondaryGloss;
739         int tex_Texture_SecondaryGlow;
740         int tex_Texture_Pants;
741         int tex_Texture_Shirt;
742         int tex_Texture_FogHeightTexture;
743         int tex_Texture_FogMask;
744         int tex_Texture_Lightmap;
745         int tex_Texture_Deluxemap;
746         int tex_Texture_Attenuation;
747         int tex_Texture_Cube;
748         int tex_Texture_Refraction;
749         int tex_Texture_Reflection;
750         int tex_Texture_ShadowMap2D;
751         int tex_Texture_CubeProjection;
752         int tex_Texture_ScreenNormalMap;
753         int tex_Texture_ScreenDiffuse;
754         int tex_Texture_ScreenSpecular;
755         int tex_Texture_ReflectMask;
756         int tex_Texture_ReflectCube;
757         int tex_Texture_BounceGrid;
758         /// locations of detected uniforms in program object, or -1 if not found
759         int loc_Texture_First;
760         int loc_Texture_Second;
761         int loc_Texture_GammaRamps;
762         int loc_Texture_Normal;
763         int loc_Texture_Color;
764         int loc_Texture_Gloss;
765         int loc_Texture_Glow;
766         int loc_Texture_SecondaryNormal;
767         int loc_Texture_SecondaryColor;
768         int loc_Texture_SecondaryGloss;
769         int loc_Texture_SecondaryGlow;
770         int loc_Texture_Pants;
771         int loc_Texture_Shirt;
772         int loc_Texture_FogHeightTexture;
773         int loc_Texture_FogMask;
774         int loc_Texture_Lightmap;
775         int loc_Texture_Deluxemap;
776         int loc_Texture_Attenuation;
777         int loc_Texture_Cube;
778         int loc_Texture_Refraction;
779         int loc_Texture_Reflection;
780         int loc_Texture_ShadowMap2D;
781         int loc_Texture_CubeProjection;
782         int loc_Texture_ScreenNormalMap;
783         int loc_Texture_ScreenDiffuse;
784         int loc_Texture_ScreenSpecular;
785         int loc_Texture_ReflectMask;
786         int loc_Texture_ReflectCube;
787         int loc_Texture_BounceGrid;
788         int loc_Alpha;
789         int loc_BloomBlur_Parameters;
790         int loc_ClientTime;
791         int loc_Color_Ambient;
792         int loc_Color_Diffuse;
793         int loc_Color_Specular;
794         int loc_Color_Glow;
795         int loc_Color_Pants;
796         int loc_Color_Shirt;
797         int loc_DeferredColor_Ambient;
798         int loc_DeferredColor_Diffuse;
799         int loc_DeferredColor_Specular;
800         int loc_DeferredMod_Diffuse;
801         int loc_DeferredMod_Specular;
802         int loc_DistortScaleRefractReflect;
803         int loc_EyePosition;
804         int loc_FogColor;
805         int loc_FogHeightFade;
806         int loc_FogPlane;
807         int loc_FogPlaneViewDist;
808         int loc_FogRangeRecip;
809         int loc_LightColor;
810         int loc_LightDir;
811         int loc_LightPosition;
812         int loc_OffsetMapping_ScaleSteps;
813         int loc_OffsetMapping_LodDistance;
814         int loc_OffsetMapping_Bias;
815         int loc_PixelSize;
816         int loc_ReflectColor;
817         int loc_ReflectFactor;
818         int loc_ReflectOffset;
819         int loc_RefractColor;
820         int loc_Saturation;
821         int loc_ScreenCenterRefractReflect;
822         int loc_ScreenScaleRefractReflect;
823         int loc_ScreenToDepth;
824         int loc_ShadowMap_Parameters;
825         int loc_ShadowMap_TextureScale;
826         int loc_SpecularPower;
827         int loc_Skeletal_Transform12;
828         int loc_UserVec1;
829         int loc_UserVec2;
830         int loc_UserVec3;
831         int loc_UserVec4;
832         int loc_ViewTintColor;
833         int loc_ViewToLight;
834         int loc_ModelToLight;
835         int loc_TexMatrix;
836         int loc_BackgroundTexMatrix;
837         int loc_ModelViewProjectionMatrix;
838         int loc_ModelViewMatrix;
839         int loc_PixelToScreenTexCoord;
840         int loc_ModelToReflectCube;
841         int loc_ShadowMapMatrix;
842         int loc_BloomColorSubtract;
843         int loc_NormalmapScrollBlend;
844         int loc_BounceGridMatrix;
845         int loc_BounceGridIntensity;
846 }
847 r_glsl_permutation_t;
848
849 #define SHADERPERMUTATION_HASHSIZE 256
850
851
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
854 enum
855 {
856         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
862         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
863         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
864         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
865         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
866         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
867         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
868         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
869 };
870 #define SHADERSTATICPARMS_COUNT 13
871
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
874
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877
878 extern qboolean r_shadow_shadowmapsampler;
879 extern int r_shadow_shadowmappcf;
880 qboolean R_CompileShader_CheckStaticParms(void)
881 {
882         static int r_compileshader_staticparms_save[1];
883         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
884         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
885
886         // detect all
887         if (r_glsl_saturation_redcompensate.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
889         if (r_glsl_vertextextureblend_usebothalphas.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
891         if (r_shadow_glossexact.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
893         if (r_glsl_postprocess.integer)
894         {
895                 if (r_glsl_postprocess_uservec1_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
897                 if (r_glsl_postprocess_uservec2_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
899                 if (r_glsl_postprocess_uservec3_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
901                 if (r_glsl_postprocess_uservec4_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
903         }
904         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
906
907         if (r_shadow_shadowmapsampler)
908                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
909         if (r_shadow_shadowmappcf > 1)
910                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
911         else if (r_shadow_shadowmappcf)
912                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
913         if (r_celshading.integer)
914                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
915         if (r_celoutlines.integer)
916                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
917
918         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
919 }
920
921 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
922         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
923                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
924         else \
925                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
926 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
927 {
928         shaderstaticparms_count = 0;
929
930         // emit all
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
940         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
941         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
942         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
943         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
944 }
945
946 /// information about each possible shader permutation
947 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
948 /// currently selected permutation
949 r_glsl_permutation_t *r_glsl_permutation;
950 /// storage for permutations linked in the hash table
951 memexpandablearray_t r_glsl_permutationarray;
952
953 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
954 {
955         //unsigned int hashdepth = 0;
956         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
957         r_glsl_permutation_t *p;
958         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
959         {
960                 if (p->mode == mode && p->permutation == permutation)
961                 {
962                         //if (hashdepth > 10)
963                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
964                         return p;
965                 }
966                 //hashdepth++;
967         }
968         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
969         p->mode = mode;
970         p->permutation = permutation;
971         p->hashnext = r_glsl_permutationhash[mode][hashindex];
972         r_glsl_permutationhash[mode][hashindex] = p;
973         //if (hashdepth > 10)
974         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
975         return p;
976 }
977
978 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
979 {
980         char *shaderstring;
981         if (!filename || !filename[0])
982                 return NULL;
983         if (!strcmp(filename, "glsl/default.glsl"))
984         {
985                 if (!glslshaderstring)
986                 {
987                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
988                         if (glslshaderstring)
989                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
990                         else
991                                 glslshaderstring = (char *)builtinshaderstring;
992                 }
993                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
994                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
995                 return shaderstring;
996         }
997         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
998         if (shaderstring)
999         {
1000                 if (printfromdisknotice)
1001                         Con_DPrintf("from disk %s... ", filename);
1002                 return shaderstring;
1003         }
1004         return shaderstring;
1005 }
1006
1007 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1008 {
1009         int i;
1010         int sampler;
1011         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1012         char *vertexstring, *geometrystring, *fragmentstring;
1013         char permutationname[256];
1014         int vertstrings_count = 0;
1015         int geomstrings_count = 0;
1016         int fragstrings_count = 0;
1017         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1018         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1019         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1020
1021         if (p->compiled)
1022                 return;
1023         p->compiled = true;
1024         p->program = 0;
1025
1026         permutationname[0] = 0;
1027         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1028         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1029         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1030
1031         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1032
1033         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1034         if(vid.support.gl20shaders130)
1035         {
1036                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1037                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1038                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1039                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1040                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1041                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1042         }
1043
1044         // the first pretext is which type of shader to compile as
1045         // (later these will all be bound together as a program object)
1046         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1047         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1048         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1049
1050         // the second pretext is the mode (for example a light source)
1051         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1052         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1053         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1054         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1055
1056         // now add all the permutation pretexts
1057         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1058         {
1059                 if (permutation & (1<<i))
1060                 {
1061                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1062                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1063                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1064                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1065                 }
1066                 else
1067                 {
1068                         // keep line numbers correct
1069                         vertstrings_list[vertstrings_count++] = "\n";
1070                         geomstrings_list[geomstrings_count++] = "\n";
1071                         fragstrings_list[fragstrings_count++] = "\n";
1072                 }
1073         }
1074
1075         // add static parms
1076         R_CompileShader_AddStaticParms(mode, permutation);
1077         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1078         vertstrings_count += shaderstaticparms_count;
1079         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1080         geomstrings_count += shaderstaticparms_count;
1081         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1082         fragstrings_count += shaderstaticparms_count;
1083
1084         // now append the shader text itself
1085         vertstrings_list[vertstrings_count++] = vertexstring;
1086         geomstrings_list[geomstrings_count++] = geometrystring;
1087         fragstrings_list[fragstrings_count++] = fragmentstring;
1088
1089         // if any sources were NULL, clear the respective list
1090         if (!vertexstring)
1091                 vertstrings_count = 0;
1092         if (!geometrystring)
1093                 geomstrings_count = 0;
1094         if (!fragmentstring)
1095                 fragstrings_count = 0;
1096
1097         // compile the shader program
1098         if (vertstrings_count + geomstrings_count + fragstrings_count)
1099                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1100         if (p->program)
1101         {
1102                 CHECKGLERROR
1103                 qglUseProgram(p->program);CHECKGLERROR
1104                 // look up all the uniform variable names we care about, so we don't
1105                 // have to look them up every time we set them
1106
1107                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1108                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1109                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1110                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1111                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1112                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1113                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1114                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1115                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1116                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1117                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1118                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1119                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1120                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1121                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1122                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1123                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1124                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1125                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1126                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1127                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1128                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1129                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1130                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1131                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1132                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1133                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1134                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1135                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1136                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1137                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1138                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1139                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1140                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1141                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1142                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1143                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1144                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1145                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1146                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1147                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1148                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1149                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1150                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1151                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1152                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1153                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1154                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1155                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1156                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1157                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1158                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1159                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1160                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1161                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1162                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1163                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1164                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1165                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1166                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1167                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1168                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1169                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1170                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1171                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1172                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1173                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1174                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1175                 p->loc_Skeletal_Transform12       = qglGetUniformLocation(p->program, "Skeletal_Transform12");
1176                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1177                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1178                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1179                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1180                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1181                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1182                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1183                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1184                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1185                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1186                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1187                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1188                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1189                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1190                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1191                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1192                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1193                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1194                 // initialize the samplers to refer to the texture units we use
1195                 p->tex_Texture_First = -1;
1196                 p->tex_Texture_Second = -1;
1197                 p->tex_Texture_GammaRamps = -1;
1198                 p->tex_Texture_Normal = -1;
1199                 p->tex_Texture_Color = -1;
1200                 p->tex_Texture_Gloss = -1;
1201                 p->tex_Texture_Glow = -1;
1202                 p->tex_Texture_SecondaryNormal = -1;
1203                 p->tex_Texture_SecondaryColor = -1;
1204                 p->tex_Texture_SecondaryGloss = -1;
1205                 p->tex_Texture_SecondaryGlow = -1;
1206                 p->tex_Texture_Pants = -1;
1207                 p->tex_Texture_Shirt = -1;
1208                 p->tex_Texture_FogHeightTexture = -1;
1209                 p->tex_Texture_FogMask = -1;
1210                 p->tex_Texture_Lightmap = -1;
1211                 p->tex_Texture_Deluxemap = -1;
1212                 p->tex_Texture_Attenuation = -1;
1213                 p->tex_Texture_Cube = -1;
1214                 p->tex_Texture_Refraction = -1;
1215                 p->tex_Texture_Reflection = -1;
1216                 p->tex_Texture_ShadowMap2D = -1;
1217                 p->tex_Texture_CubeProjection = -1;
1218                 p->tex_Texture_ScreenNormalMap = -1;
1219                 p->tex_Texture_ScreenDiffuse = -1;
1220                 p->tex_Texture_ScreenSpecular = -1;
1221                 p->tex_Texture_ReflectMask = -1;
1222                 p->tex_Texture_ReflectCube = -1;
1223                 p->tex_Texture_BounceGrid = -1;
1224                 sampler = 0;
1225                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1226                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1227                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1228                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1229                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1230                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1231                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1232                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1233                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1234                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1235                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1236                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1237                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1238                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1239                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1240                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1241                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1242                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1243                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1244                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1245                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1246                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1247                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1248                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1249                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1250                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1251                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1252                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1253                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1254                 CHECKGLERROR
1255                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1256         }
1257         else
1258                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1259
1260         // free the strings
1261         if (vertexstring)
1262                 Mem_Free(vertexstring);
1263         if (geometrystring)
1264                 Mem_Free(geometrystring);
1265         if (fragmentstring)
1266                 Mem_Free(fragmentstring);
1267 }
1268
1269 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1270 {
1271         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1272         if (r_glsl_permutation != perm)
1273         {
1274                 r_glsl_permutation = perm;
1275                 if (!r_glsl_permutation->program)
1276                 {
1277                         if (!r_glsl_permutation->compiled)
1278                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1279                         if (!r_glsl_permutation->program)
1280                         {
1281                                 // remove features until we find a valid permutation
1282                                 int i;
1283                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1284                                 {
1285                                         // reduce i more quickly whenever it would not remove any bits
1286                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1287                                         if (!(permutation & j))
1288                                                 continue;
1289                                         permutation -= j;
1290                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291                                         if (!r_glsl_permutation->compiled)
1292                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1293                                         if (r_glsl_permutation->program)
1294                                                 break;
1295                                 }
1296                                 if (i >= SHADERPERMUTATION_COUNT)
1297                                 {
1298                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1299                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1300                                         qglUseProgram(0);CHECKGLERROR
1301                                         return; // no bit left to clear, entire mode is broken
1302                                 }
1303                         }
1304                 }
1305                 CHECKGLERROR
1306                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1307         }
1308         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1309         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1310         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1311 }
1312
1313 #ifdef SUPPORTD3D
1314
1315 #ifdef SUPPORTD3D
1316 #include <d3d9.h>
1317 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1318 extern D3DCAPS9 vid_d3d9caps;
1319 #endif
1320
1321 struct r_hlsl_permutation_s;
1322 typedef struct r_hlsl_permutation_s
1323 {
1324         /// hash lookup data
1325         struct r_hlsl_permutation_s *hashnext;
1326         unsigned int mode;
1327         unsigned int permutation;
1328
1329         /// indicates if we have tried compiling this permutation already
1330         qboolean compiled;
1331         /// NULL if compilation failed
1332         IDirect3DVertexShader9 *vertexshader;
1333         IDirect3DPixelShader9 *pixelshader;
1334 }
1335 r_hlsl_permutation_t;
1336
1337 typedef enum D3DVSREGISTER_e
1338 {
1339         D3DVSREGISTER_TexMatrix = 0, // float4x4
1340         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1341         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1342         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1343         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1344         D3DVSREGISTER_ModelToLight = 20, // float4x4
1345         D3DVSREGISTER_EyePosition = 24,
1346         D3DVSREGISTER_FogPlane = 25,
1347         D3DVSREGISTER_LightDir = 26,
1348         D3DVSREGISTER_LightPosition = 27,
1349 }
1350 D3DVSREGISTER_t;
1351
1352 typedef enum D3DPSREGISTER_e
1353 {
1354         D3DPSREGISTER_Alpha = 0,
1355         D3DPSREGISTER_BloomBlur_Parameters = 1,
1356         D3DPSREGISTER_ClientTime = 2,
1357         D3DPSREGISTER_Color_Ambient = 3,
1358         D3DPSREGISTER_Color_Diffuse = 4,
1359         D3DPSREGISTER_Color_Specular = 5,
1360         D3DPSREGISTER_Color_Glow = 6,
1361         D3DPSREGISTER_Color_Pants = 7,
1362         D3DPSREGISTER_Color_Shirt = 8,
1363         D3DPSREGISTER_DeferredColor_Ambient = 9,
1364         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1365         D3DPSREGISTER_DeferredColor_Specular = 11,
1366         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1367         D3DPSREGISTER_DeferredMod_Specular = 13,
1368         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1369         D3DPSREGISTER_EyePosition = 15, // unused
1370         D3DPSREGISTER_FogColor = 16,
1371         D3DPSREGISTER_FogHeightFade = 17,
1372         D3DPSREGISTER_FogPlane = 18,
1373         D3DPSREGISTER_FogPlaneViewDist = 19,
1374         D3DPSREGISTER_FogRangeRecip = 20,
1375         D3DPSREGISTER_LightColor = 21,
1376         D3DPSREGISTER_LightDir = 22, // unused
1377         D3DPSREGISTER_LightPosition = 23,
1378         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1379         D3DPSREGISTER_PixelSize = 25,
1380         D3DPSREGISTER_ReflectColor = 26,
1381         D3DPSREGISTER_ReflectFactor = 27,
1382         D3DPSREGISTER_ReflectOffset = 28,
1383         D3DPSREGISTER_RefractColor = 29,
1384         D3DPSREGISTER_Saturation = 30,
1385         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1386         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1387         D3DPSREGISTER_ScreenToDepth = 33,
1388         D3DPSREGISTER_ShadowMap_Parameters = 34,
1389         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1390         D3DPSREGISTER_SpecularPower = 36,
1391         D3DPSREGISTER_UserVec1 = 37,
1392         D3DPSREGISTER_UserVec2 = 38,
1393         D3DPSREGISTER_UserVec3 = 39,
1394         D3DPSREGISTER_UserVec4 = 40,
1395         D3DPSREGISTER_ViewTintColor = 41,
1396         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1397         D3DPSREGISTER_BloomColorSubtract = 43,
1398         D3DPSREGISTER_ViewToLight = 44, // float4x4
1399         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1400         D3DPSREGISTER_NormalmapScrollBlend = 52,
1401         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1402         D3DPSREGISTER_OffsetMapping_Bias = 54,
1403         // next at 54
1404 }
1405 D3DPSREGISTER_t;
1406
1407 /// information about each possible shader permutation
1408 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1409 /// currently selected permutation
1410 r_hlsl_permutation_t *r_hlsl_permutation;
1411 /// storage for permutations linked in the hash table
1412 memexpandablearray_t r_hlsl_permutationarray;
1413
1414 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1415 {
1416         //unsigned int hashdepth = 0;
1417         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1418         r_hlsl_permutation_t *p;
1419         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1420         {
1421                 if (p->mode == mode && p->permutation == permutation)
1422                 {
1423                         //if (hashdepth > 10)
1424                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1425                         return p;
1426                 }
1427                 //hashdepth++;
1428         }
1429         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1430         p->mode = mode;
1431         p->permutation = permutation;
1432         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1433         r_hlsl_permutationhash[mode][hashindex] = p;
1434         //if (hashdepth > 10)
1435         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1436         return p;
1437 }
1438
1439 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1440 {
1441         char *shaderstring;
1442         if (!filename || !filename[0])
1443                 return NULL;
1444         if (!strcmp(filename, "hlsl/default.hlsl"))
1445         {
1446                 if (!hlslshaderstring)
1447                 {
1448                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1449                         if (hlslshaderstring)
1450                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1451                         else
1452                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1453                 }
1454                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1455                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1456                 return shaderstring;
1457         }
1458         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1459         if (shaderstring)
1460         {
1461                 if (printfromdisknotice)
1462                         Con_DPrintf("from disk %s... ", filename);
1463                 return shaderstring;
1464         }
1465         return shaderstring;
1466 }
1467
1468 #include <d3dx9.h>
1469 //#include <d3dx9shader.h>
1470 //#include <d3dx9mesh.h>
1471
1472 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1473 {
1474         DWORD *vsbin = NULL;
1475         DWORD *psbin = NULL;
1476         fs_offset_t vsbinsize;
1477         fs_offset_t psbinsize;
1478 //      IDirect3DVertexShader9 *vs = NULL;
1479 //      IDirect3DPixelShader9 *ps = NULL;
1480         ID3DXBuffer *vslog = NULL;
1481         ID3DXBuffer *vsbuffer = NULL;
1482         ID3DXConstantTable *vsconstanttable = NULL;
1483         ID3DXBuffer *pslog = NULL;
1484         ID3DXBuffer *psbuffer = NULL;
1485         ID3DXConstantTable *psconstanttable = NULL;
1486         int vsresult = 0;
1487         int psresult = 0;
1488         char temp[MAX_INPUTLINE];
1489         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1490         char vabuf[1024];
1491         qboolean debugshader = gl_paranoid.integer != 0;
1492         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1493         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1494         if (!debugshader)
1495         {
1496                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1497                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1498         }
1499         if ((!vsbin && vertstring) || (!psbin && fragstring))
1500         {
1501                 const char* dllnames_d3dx9 [] =
1502                 {
1503                         "d3dx9_43.dll",
1504                         "d3dx9_42.dll",
1505                         "d3dx9_41.dll",
1506                         "d3dx9_40.dll",
1507                         "d3dx9_39.dll",
1508                         "d3dx9_38.dll",
1509                         "d3dx9_37.dll",
1510                         "d3dx9_36.dll",
1511                         "d3dx9_35.dll",
1512                         "d3dx9_34.dll",
1513                         "d3dx9_33.dll",
1514                         "d3dx9_32.dll",
1515                         "d3dx9_31.dll",
1516                         "d3dx9_30.dll",
1517                         "d3dx9_29.dll",
1518                         "d3dx9_28.dll",
1519                         "d3dx9_27.dll",
1520                         "d3dx9_26.dll",
1521                         "d3dx9_25.dll",
1522                         "d3dx9_24.dll",
1523                         NULL
1524                 };
1525                 dllhandle_t d3dx9_dll = NULL;
1526                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1527                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1528                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1529                 dllfunction_t d3dx9_dllfuncs[] =
1530                 {
1531                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1532                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1533                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1534                         {NULL, NULL}
1535                 };
1536                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1537                 {
1538                         DWORD shaderflags = 0;
1539                         if (debugshader)
1540                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1541                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1542                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1543                         if (vertstring && vertstring[0])
1544                         {
1545                                 if (debugshader)
1546                                 {
1547                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1548                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1549                                 }
1550                                 else
1551                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1552                                 if (vsbuffer)
1553                                 {
1554                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1555                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1556                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1557                                         ID3DXBuffer_Release(vsbuffer);
1558                                 }
1559                                 if (vslog)
1560                                 {
1561                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1562                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1563                                         ID3DXBuffer_Release(vslog);
1564                                 }
1565                         }
1566                         if (fragstring && fragstring[0])
1567                         {
1568                                 if (debugshader)
1569                                 {
1570                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1571                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1572                                 }
1573                                 else
1574                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1575                                 if (psbuffer)
1576                                 {
1577                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1578                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1579                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1580                                         ID3DXBuffer_Release(psbuffer);
1581                                 }
1582                                 if (pslog)
1583                                 {
1584                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1585                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1586                                         ID3DXBuffer_Release(pslog);
1587                                 }
1588                         }
1589                         Sys_UnloadLibrary(&d3dx9_dll);
1590                 }
1591                 else
1592                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1593         }
1594         if (vsbin && psbin)
1595         {
1596                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1597                 if (FAILED(vsresult))
1598                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1599                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1600                 if (FAILED(psresult))
1601                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1602         }
1603         // free the shader data
1604         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1605         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1606 }
1607
1608 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1609 {
1610         int i;
1611         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1612         int vertstring_length = 0;
1613         int geomstring_length = 0;
1614         int fragstring_length = 0;
1615         char *t;
1616         char *vertexstring, *geometrystring, *fragmentstring;
1617         char *vertstring, *geomstring, *fragstring;
1618         char permutationname[256];
1619         char cachename[256];
1620         int vertstrings_count = 0;
1621         int geomstrings_count = 0;
1622         int fragstrings_count = 0;
1623         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1624         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1625         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1626
1627         if (p->compiled)
1628                 return;
1629         p->compiled = true;
1630         p->vertexshader = NULL;
1631         p->pixelshader = NULL;
1632
1633         permutationname[0] = 0;
1634         cachename[0] = 0;
1635         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1636         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1637         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1638
1639         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1640         strlcat(cachename, "hlsl/", sizeof(cachename));
1641
1642         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1643         vertstrings_count = 0;
1644         geomstrings_count = 0;
1645         fragstrings_count = 0;
1646         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1647         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1648         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1649
1650         // the first pretext is which type of shader to compile as
1651         // (later these will all be bound together as a program object)
1652         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1653         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1654         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1655
1656         // the second pretext is the mode (for example a light source)
1657         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1658         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1659         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1660         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1661         strlcat(cachename, modeinfo->name, sizeof(cachename));
1662
1663         // now add all the permutation pretexts
1664         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1665         {
1666                 if (permutation & (1<<i))
1667                 {
1668                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1669                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1670                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1671                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1672                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1673                 }
1674                 else
1675                 {
1676                         // keep line numbers correct
1677                         vertstrings_list[vertstrings_count++] = "\n";
1678                         geomstrings_list[geomstrings_count++] = "\n";
1679                         fragstrings_list[fragstrings_count++] = "\n";
1680                 }
1681         }
1682
1683         // add static parms
1684         R_CompileShader_AddStaticParms(mode, permutation);
1685         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1686         vertstrings_count += shaderstaticparms_count;
1687         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1688         geomstrings_count += shaderstaticparms_count;
1689         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1690         fragstrings_count += shaderstaticparms_count;
1691
1692         // replace spaces in the cachename with _ characters
1693         for (i = 0;cachename[i];i++)
1694                 if (cachename[i] == ' ')
1695                         cachename[i] = '_';
1696
1697         // now append the shader text itself
1698         vertstrings_list[vertstrings_count++] = vertexstring;
1699         geomstrings_list[geomstrings_count++] = geometrystring;
1700         fragstrings_list[fragstrings_count++] = fragmentstring;
1701
1702         // if any sources were NULL, clear the respective list
1703         if (!vertexstring)
1704                 vertstrings_count = 0;
1705         if (!geometrystring)
1706                 geomstrings_count = 0;
1707         if (!fragmentstring)
1708                 fragstrings_count = 0;
1709
1710         vertstring_length = 0;
1711         for (i = 0;i < vertstrings_count;i++)
1712                 vertstring_length += strlen(vertstrings_list[i]);
1713         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1714         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1715                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1716
1717         geomstring_length = 0;
1718         for (i = 0;i < geomstrings_count;i++)
1719                 geomstring_length += strlen(geomstrings_list[i]);
1720         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1721         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1722                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1723
1724         fragstring_length = 0;
1725         for (i = 0;i < fragstrings_count;i++)
1726                 fragstring_length += strlen(fragstrings_list[i]);
1727         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1728         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1729                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1730
1731         // try to load the cached shader, or generate one
1732         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1733
1734         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1735                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1736         else
1737                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1738
1739         // free the strings
1740         if (vertstring)
1741                 Mem_Free(vertstring);
1742         if (geomstring)
1743                 Mem_Free(geomstring);
1744         if (fragstring)
1745                 Mem_Free(fragstring);
1746         if (vertexstring)
1747                 Mem_Free(vertexstring);
1748         if (geometrystring)
1749                 Mem_Free(geometrystring);
1750         if (fragmentstring)
1751                 Mem_Free(fragmentstring);
1752 }
1753
1754 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1755 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1756 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);}
1757 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);}
1758 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);}
1759 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);}
1760
1761 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1762 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1763 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);}
1764 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);}
1765 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);}
1766 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);}
1767
1768 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1769 {
1770         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1771         if (r_hlsl_permutation != perm)
1772         {
1773                 r_hlsl_permutation = perm;
1774                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1775                 {
1776                         if (!r_hlsl_permutation->compiled)
1777                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1778                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1779                         {
1780                                 // remove features until we find a valid permutation
1781                                 int i;
1782                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1783                                 {
1784                                         // reduce i more quickly whenever it would not remove any bits
1785                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1786                                         if (!(permutation & j))
1787                                                 continue;
1788                                         permutation -= j;
1789                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1790                                         if (!r_hlsl_permutation->compiled)
1791                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1792                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1793                                                 break;
1794                                 }
1795                                 if (i >= SHADERPERMUTATION_COUNT)
1796                                 {
1797                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1798                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1799                                         return; // no bit left to clear, entire mode is broken
1800                                 }
1801                         }
1802                 }
1803                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1804                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1805         }
1806         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1807         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1808         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1809 }
1810 #endif
1811
1812 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1813 {
1814         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1815         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1816         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1817         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1818 }
1819
1820 void R_GLSL_Restart_f(void)
1821 {
1822         unsigned int i, limit;
1823         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1824                 Mem_Free(glslshaderstring);
1825         glslshaderstring = NULL;
1826         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1827                 Mem_Free(hlslshaderstring);
1828         hlslshaderstring = NULL;
1829         switch(vid.renderpath)
1830         {
1831         case RENDERPATH_D3D9:
1832 #ifdef SUPPORTD3D
1833                 {
1834                         r_hlsl_permutation_t *p;
1835                         r_hlsl_permutation = NULL;
1836                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1837                         for (i = 0;i < limit;i++)
1838                         {
1839                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1840                                 {
1841                                         if (p->vertexshader)
1842                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1843                                         if (p->pixelshader)
1844                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1845                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1846                                 }
1847                         }
1848                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1849                 }
1850 #endif
1851                 break;
1852         case RENDERPATH_D3D10:
1853                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1854                 break;
1855         case RENDERPATH_D3D11:
1856                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1857                 break;
1858         case RENDERPATH_GL20:
1859         case RENDERPATH_GLES2:
1860                 {
1861                         r_glsl_permutation_t *p;
1862                         r_glsl_permutation = NULL;
1863                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1864                         for (i = 0;i < limit;i++)
1865                         {
1866                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1867                                 {
1868                                         GL_Backend_FreeProgram(p->program);
1869                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1870                                 }
1871                         }
1872                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1873                 }
1874                 break;
1875         case RENDERPATH_GL11:
1876         case RENDERPATH_GL13:
1877         case RENDERPATH_GLES1:
1878                 break;
1879         case RENDERPATH_SOFT:
1880                 break;
1881         }
1882 }
1883
1884 static void R_GLSL_DumpShader_f(void)
1885 {
1886         int i;
1887         qfile_t *file;
1888
1889         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1890         if (file)
1891         {
1892                 FS_Print(file, "/* The engine may define the following macros:\n");
1893                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1894                 for (i = 0;i < SHADERMODE_COUNT;i++)
1895                         FS_Print(file, glslshadermodeinfo[i].pretext);
1896                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1897                         FS_Print(file, shaderpermutationinfo[i].pretext);
1898                 FS_Print(file, "*/\n");
1899                 FS_Print(file, builtinshaderstring);
1900                 FS_Close(file);
1901                 Con_Printf("glsl/default.glsl written\n");
1902         }
1903         else
1904                 Con_Printf("failed to write to glsl/default.glsl\n");
1905
1906         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1907         if (file)
1908         {
1909                 FS_Print(file, "/* The engine may define the following macros:\n");
1910                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1911                 for (i = 0;i < SHADERMODE_COUNT;i++)
1912                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1913                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1914                         FS_Print(file, shaderpermutationinfo[i].pretext);
1915                 FS_Print(file, "*/\n");
1916                 FS_Print(file, builtinhlslshaderstring);
1917                 FS_Close(file);
1918                 Con_Printf("hlsl/default.hlsl written\n");
1919         }
1920         else
1921                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1922 }
1923
1924 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1925 {
1926         unsigned int permutation = 0;
1927         if (r_trippy.integer && !notrippy)
1928                 permutation |= SHADERPERMUTATION_TRIPPY;
1929         permutation |= SHADERPERMUTATION_VIEWTINT;
1930         if (first)
1931                 permutation |= SHADERPERMUTATION_DIFFUSE;
1932         if (second)
1933                 permutation |= SHADERPERMUTATION_SPECULAR;
1934         if (texturemode == GL_MODULATE)
1935                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1936         else if (texturemode == GL_ADD)
1937                 permutation |= SHADERPERMUTATION_GLOW;
1938         else if (texturemode == GL_DECAL)
1939                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1940         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1941                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1942         if (suppresstexalpha)
1943                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1944         if (!second)
1945                 texturemode = GL_MODULATE;
1946         if (vid.allowalphatocoverage)
1947                 GL_AlphaToCoverage(false);
1948         switch (vid.renderpath)
1949         {
1950         case RENDERPATH_D3D9:
1951 #ifdef SUPPORTD3D
1952                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1953                 R_Mesh_TexBind(GL20TU_FIRST , first );
1954                 R_Mesh_TexBind(GL20TU_SECOND, second);
1955                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1956                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1957 #endif
1958                 break;
1959         case RENDERPATH_D3D10:
1960                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961                 break;
1962         case RENDERPATH_D3D11:
1963                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964                 break;
1965         case RENDERPATH_GL20:
1966         case RENDERPATH_GLES2:
1967                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1968                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1969                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1970                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1971                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1972                 break;
1973         case RENDERPATH_GL13:
1974         case RENDERPATH_GLES1:
1975                 R_Mesh_TexBind(0, first );
1976                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1977                 R_Mesh_TexBind(1, second);
1978                 if (second)
1979                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1980                 break;
1981         case RENDERPATH_GL11:
1982                 R_Mesh_TexBind(0, first );
1983                 break;
1984         case RENDERPATH_SOFT:
1985                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1986                 R_Mesh_TexBind(GL20TU_FIRST , first );
1987                 R_Mesh_TexBind(GL20TU_SECOND, second);
1988                 break;
1989         }
1990 }
1991
1992 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1993 {
1994         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1995 }
1996
1997 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1998 {
1999         unsigned int permutation = 0;
2000         if (r_trippy.integer && !notrippy)
2001                 permutation |= SHADERPERMUTATION_TRIPPY;
2002         if (depthrgb)
2003                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2004         if (vid.allowalphatocoverage)
2005                 GL_AlphaToCoverage(false);
2006         switch (vid.renderpath)
2007         {
2008         case RENDERPATH_D3D9:
2009 #ifdef SUPPORTD3D
2010                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2011 #endif
2012                 break;
2013         case RENDERPATH_D3D10:
2014                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2015                 break;
2016         case RENDERPATH_D3D11:
2017                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2018                 break;
2019         case RENDERPATH_GL20:
2020         case RENDERPATH_GLES2:
2021                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2022                 break;
2023         case RENDERPATH_GL13:
2024         case RENDERPATH_GLES1:
2025                 R_Mesh_TexBind(0, 0);
2026                 R_Mesh_TexBind(1, 0);
2027                 break;
2028         case RENDERPATH_GL11:
2029                 R_Mesh_TexBind(0, 0);
2030                 break;
2031         case RENDERPATH_SOFT:
2032                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2033                 break;
2034         }
2035 }
2036
2037 void R_SetupShader_ShowDepth(qboolean notrippy)
2038 {
2039         int permutation = 0;
2040         if (r_trippy.integer && !notrippy)
2041                 permutation |= SHADERPERMUTATION_TRIPPY;
2042         if (vid.allowalphatocoverage)
2043                 GL_AlphaToCoverage(false);
2044         switch (vid.renderpath)
2045         {
2046         case RENDERPATH_D3D9:
2047 #ifdef SUPPORTHLSL
2048                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2049 #endif
2050                 break;
2051         case RENDERPATH_D3D10:
2052                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2053                 break;
2054         case RENDERPATH_D3D11:
2055                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2056                 break;
2057         case RENDERPATH_GL20:
2058         case RENDERPATH_GLES2:
2059                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2060                 break;
2061         case RENDERPATH_GL13:
2062         case RENDERPATH_GLES1:
2063                 break;
2064         case RENDERPATH_GL11:
2065                 break;
2066         case RENDERPATH_SOFT:
2067                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2068                 break;
2069         }
2070 }
2071
2072 extern qboolean r_shadow_usingdeferredprepass;
2073 extern rtexture_t *r_shadow_attenuationgradienttexture;
2074 extern rtexture_t *r_shadow_attenuation2dtexture;
2075 extern rtexture_t *r_shadow_attenuation3dtexture;
2076 extern qboolean r_shadow_usingshadowmap2d;
2077 extern qboolean r_shadow_usingshadowmaportho;
2078 extern float r_shadow_shadowmap_texturescale[2];
2079 extern float r_shadow_shadowmap_parameters[4];
2080 extern qboolean r_shadow_shadowmapvsdct;
2081 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2082 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2083 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2084 extern matrix4x4_t r_shadow_shadowmapmatrix;
2085 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2086 extern int r_shadow_prepass_width;
2087 extern int r_shadow_prepass_height;
2088 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2089 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2090 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2091 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2092
2093 #define BLENDFUNC_ALLOWS_COLORMOD      1
2094 #define BLENDFUNC_ALLOWS_FOG           2
2095 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2096 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2097 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2098 static int R_BlendFuncFlags(int src, int dst)
2099 {
2100         int r = 0;
2101
2102         // a blendfunc allows colormod if:
2103         // a) it can never keep the destination pixel invariant, or
2104         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2105         // this is to prevent unintended side effects from colormod
2106
2107         // a blendfunc allows fog if:
2108         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2109         // this is to prevent unintended side effects from fog
2110
2111         // these checks are the output of fogeval.pl
2112
2113         r |= BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2115         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2116         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2117         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2118         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2120         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2121         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2122         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2123         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2124         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2125         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2126         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2127         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2128         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2129         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2130         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2132         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2133         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2134         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2135
2136         return r;
2137 }
2138
2139 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)
2140 {
2141         // select a permutation of the lighting shader appropriate to this
2142         // combination of texture, entity, light source, and fogging, only use the
2143         // minimum features necessary to avoid wasting rendering time in the
2144         // fragment shader on features that are not being used
2145         unsigned int permutation = 0;
2146         unsigned int mode = 0;
2147         int blendfuncflags;
2148         static float dummy_colormod[3] = {1, 1, 1};
2149         float *colormod = rsurface.colormod;
2150         float m16f[16];
2151         matrix4x4_t tempmatrix;
2152         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2153         if (r_trippy.integer && !notrippy)
2154                 permutation |= SHADERPERMUTATION_TRIPPY;
2155         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2156                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2157         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2158                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2159         if (rsurfacepass == RSURFPASS_BACKGROUND)
2160         {
2161                 // distorted background
2162                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2163                 {
2164                         mode = SHADERMODE_WATER;
2165                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2166                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2167                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2168                         {
2169                                 // this is the right thing to do for wateralpha
2170                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2171                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2172                         }
2173                         else
2174                         {
2175                                 // this is the right thing to do for entity alpha
2176                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2177                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2178                         }
2179                 }
2180                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2181                 {
2182                         mode = SHADERMODE_REFRACTION;
2183                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2184                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2185                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2186                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2187                 }
2188                 else
2189                 {
2190                         mode = SHADERMODE_GENERIC;
2191                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2192                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2193                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2194                 }
2195                 if (vid.allowalphatocoverage)
2196                         GL_AlphaToCoverage(false);
2197         }
2198         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2199         {
2200                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2201                 {
2202                         switch(rsurface.texture->offsetmapping)
2203                         {
2204                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2205                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2206                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207                         case OFFSETMAPPING_OFF: break;
2208                         }
2209                 }
2210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2211                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2212                 // normalmap (deferred prepass), may use alpha test on diffuse
2213                 mode = SHADERMODE_DEFERREDGEOMETRY;
2214                 GL_BlendFunc(GL_ONE, GL_ZERO);
2215                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2216                 if (vid.allowalphatocoverage)
2217                         GL_AlphaToCoverage(false);
2218         }
2219         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2220         {
2221                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2222                 {
2223                         switch(rsurface.texture->offsetmapping)
2224                         {
2225                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2226                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2227                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2228                         case OFFSETMAPPING_OFF: break;
2229                         }
2230                 }
2231                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2232                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2233                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2234                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2235                 // light source
2236                 mode = SHADERMODE_LIGHTSOURCE;
2237                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2238                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2239                 if (diffusescale > 0)
2240                         permutation |= SHADERPERMUTATION_DIFFUSE;
2241                 if (specularscale > 0)
2242                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2243                 if (r_refdef.fogenabled)
2244                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2245                 if (rsurface.texture->colormapping)
2246                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2247                 if (r_shadow_usingshadowmap2d)
2248                 {
2249                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2250                         if(r_shadow_shadowmapvsdct)
2251                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2252
2253                         if (r_shadow_shadowmap2ddepthbuffer)
2254                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2255                 }
2256                 if (rsurface.texture->reflectmasktexture)
2257                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2258                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2259                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2260                 if (vid.allowalphatocoverage)
2261                         GL_AlphaToCoverage(false);
2262         }
2263         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2264         {
2265                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2266                 {
2267                         switch(rsurface.texture->offsetmapping)
2268                         {
2269                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2270                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2271                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2272                         case OFFSETMAPPING_OFF: break;
2273                         }
2274                 }
2275                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2276                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2277                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2278                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2279                 // unshaded geometry (fullbright or ambient model lighting)
2280                 mode = SHADERMODE_FLATCOLOR;
2281                 ambientscale = diffusescale = specularscale = 0;
2282                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2283                         permutation |= SHADERPERMUTATION_GLOW;
2284                 if (r_refdef.fogenabled)
2285                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2286                 if (rsurface.texture->colormapping)
2287                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2288                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2289                 {
2290                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2291                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2292
2293                         if (r_shadow_shadowmap2ddepthbuffer)
2294                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2295                 }
2296                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2297                         permutation |= SHADERPERMUTATION_REFLECTION;
2298                 if (rsurface.texture->reflectmasktexture)
2299                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2300                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2301                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2302                 // when using alphatocoverage, we don't need alphakill
2303                 if (vid.allowalphatocoverage)
2304                 {
2305                         if (r_transparent_alphatocoverage.integer)
2306                         {
2307                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2308                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2309                         }
2310                         else
2311                                 GL_AlphaToCoverage(false);
2312                 }
2313         }
2314         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2315         {
2316                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2317                 {
2318                         switch(rsurface.texture->offsetmapping)
2319                         {
2320                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2321                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2322                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2323                         case OFFSETMAPPING_OFF: break;
2324                         }
2325                 }
2326                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2327                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2328                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2329                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2330                 // directional model lighting
2331                 mode = SHADERMODE_LIGHTDIRECTION;
2332                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2333                         permutation |= SHADERPERMUTATION_GLOW;
2334                 permutation |= SHADERPERMUTATION_DIFFUSE;
2335                 if (specularscale > 0)
2336                         permutation |= SHADERPERMUTATION_SPECULAR;
2337                 if (r_refdef.fogenabled)
2338                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2339                 if (rsurface.texture->colormapping)
2340                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2341                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2342                 {
2343                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2344                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2345
2346                         if (r_shadow_shadowmap2ddepthbuffer)
2347                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2348                 }
2349                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2350                         permutation |= SHADERPERMUTATION_REFLECTION;
2351                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2352                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2353                 if (rsurface.texture->reflectmasktexture)
2354                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2355                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2356                 {
2357                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2358                         if (r_shadow_bouncegriddirectional)
2359                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2360                 }
2361                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2362                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2363                 // when using alphatocoverage, we don't need alphakill
2364                 if (vid.allowalphatocoverage)
2365                 {
2366                         if (r_transparent_alphatocoverage.integer)
2367                         {
2368                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2369                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2370                         }
2371                         else
2372                                 GL_AlphaToCoverage(false);
2373                 }
2374         }
2375         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2376         {
2377                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2378                 {
2379                         switch(rsurface.texture->offsetmapping)
2380                         {
2381                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2382                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2383                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2384                         case OFFSETMAPPING_OFF: break;
2385                         }
2386                 }
2387                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2388                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2390                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2391                 // ambient model lighting
2392                 mode = SHADERMODE_LIGHTDIRECTION;
2393                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2394                         permutation |= SHADERPERMUTATION_GLOW;
2395                 if (r_refdef.fogenabled)
2396                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2397                 if (rsurface.texture->colormapping)
2398                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2399                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2400                 {
2401                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2402                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2403
2404                         if (r_shadow_shadowmap2ddepthbuffer)
2405                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2406                 }
2407                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2408                         permutation |= SHADERPERMUTATION_REFLECTION;
2409                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2410                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2411                 if (rsurface.texture->reflectmasktexture)
2412                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2413                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2414                 {
2415                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2416                         if (r_shadow_bouncegriddirectional)
2417                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2418                 }
2419                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421                 // when using alphatocoverage, we don't need alphakill
2422                 if (vid.allowalphatocoverage)
2423                 {
2424                         if (r_transparent_alphatocoverage.integer)
2425                         {
2426                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2427                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2428                         }
2429                         else
2430                                 GL_AlphaToCoverage(false);
2431                 }
2432         }
2433         else
2434         {
2435                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2436                 {
2437                         switch(rsurface.texture->offsetmapping)
2438                         {
2439                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2440                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2441                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2442                         case OFFSETMAPPING_OFF: break;
2443                         }
2444                 }
2445                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2446                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2447                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2448                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2449                 // lightmapped wall
2450                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2451                         permutation |= SHADERPERMUTATION_GLOW;
2452                 if (r_refdef.fogenabled)
2453                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2454                 if (rsurface.texture->colormapping)
2455                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2456                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2457                 {
2458                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2459                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2460
2461                         if (r_shadow_shadowmap2ddepthbuffer)
2462                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2463                 }
2464                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2465                         permutation |= SHADERPERMUTATION_REFLECTION;
2466                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2467                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2468                 if (rsurface.texture->reflectmasktexture)
2469                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2470                 if (FAKELIGHT_ENABLED)
2471                 {
2472                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2473                         mode = SHADERMODE_FAKELIGHT;
2474                         permutation |= SHADERPERMUTATION_DIFFUSE;
2475                         if (specularscale > 0)
2476                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2477                 }
2478                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2479                 {
2480                         // deluxemapping (light direction texture)
2481                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2482                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2483                         else
2484                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2485                         permutation |= SHADERPERMUTATION_DIFFUSE;
2486                         if (specularscale > 0)
2487                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2488                 }
2489                 else if (r_glsl_deluxemapping.integer >= 2)
2490                 {
2491                         // fake deluxemapping (uniform light direction in tangentspace)
2492                         if (rsurface.uselightmaptexture)
2493                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2494                         else
2495                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2496                         permutation |= SHADERPERMUTATION_DIFFUSE;
2497                         if (specularscale > 0)
2498                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2499                 }
2500                 else if (rsurface.uselightmaptexture)
2501                 {
2502                         // ordinary lightmapping (q1bsp, q3bsp)
2503                         mode = SHADERMODE_LIGHTMAP;
2504                 }
2505                 else
2506                 {
2507                         // ordinary vertex coloring (q3bsp)
2508                         mode = SHADERMODE_VERTEXCOLOR;
2509                 }
2510                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2511                 {
2512                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2513                         if (r_shadow_bouncegriddirectional)
2514                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2515                 }
2516                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2517                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2518                 // when using alphatocoverage, we don't need alphakill
2519                 if (vid.allowalphatocoverage)
2520                 {
2521                         if (r_transparent_alphatocoverage.integer)
2522                         {
2523                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2524                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2525                         }
2526                         else
2527                                 GL_AlphaToCoverage(false);
2528                 }
2529         }
2530         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2531                 colormod = dummy_colormod;
2532         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2533                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2534         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2535                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2536         switch(vid.renderpath)
2537         {
2538         case RENDERPATH_D3D9:
2539 #ifdef SUPPORTD3D
2540                 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2541                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2542                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2543                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2544                 if (mode == SHADERMODE_LIGHTSOURCE)
2545                 {
2546                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2547                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2548                 }
2549                 else
2550                 {
2551                         if (mode == SHADERMODE_LIGHTDIRECTION)
2552                         {
2553                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2554                         }
2555                 }
2556                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2557                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2558                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2559                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2560                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2561
2562                 if (mode == SHADERMODE_LIGHTSOURCE)
2563                 {
2564                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2565                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2566                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2567                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2568                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2569
2570                         // additive passes are only darkened by fog, not tinted
2571                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2572                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2573                 }
2574                 else
2575                 {
2576                         if (mode == SHADERMODE_FLATCOLOR)
2577                         {
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2579                         }
2580                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2581                         {
2582                                 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]);
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2584                                 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);
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2589                         }
2590                         else
2591                         {
2592                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2593                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2594                                 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);
2595                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2597                         }
2598                         // additive passes are only darkened by fog, not tinted
2599                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2600                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2601                         else
2602                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2603                         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);
2604                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2605                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2606                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2607                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2608                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2609                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2610                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2611                         if (mode == SHADERMODE_WATER)
2612                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2613                 }
2614                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2615                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2616                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2617                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2618                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2619                 if (rsurface.texture->pantstexture)
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2621                 else
2622                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2623                 if (rsurface.texture->shirttexture)
2624                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2625                 else
2626                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2627                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2628                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2629                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2630                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2631                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2632                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2633                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2634                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2635                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2636                         );
2637                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2638                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2639                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2640                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2641
2642                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2643                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2644                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2645                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2646                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2647                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2648                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2649                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2650                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2651                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2652                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2653                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2654                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2655                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2656                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2657                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2658                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2659                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2660                 {
2661                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2662                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2663                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2664                 }
2665                 else
2666                 {
2667                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2668                 }
2669 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2670                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2671                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2672                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2673                 {
2674                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2675                         if (rsurface.rtlight)
2676                         {
2677                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2678                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2679                         }
2680                 }
2681 #endif
2682                 break;
2683         case RENDERPATH_D3D10:
2684                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2685                 break;
2686         case RENDERPATH_D3D11:
2687                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2688                 break;
2689         case RENDERPATH_GL20:
2690         case RENDERPATH_GLES2:
2691                 if (!vid.useinterleavedarrays)
2692                 {
2693                         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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2694                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2695                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2696                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2697                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2698                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2699                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2700                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2701                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2702                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2703                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2704                 }
2705                 else
2706                 {
2707                         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) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2708                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2709                 }
2710                 // this has to be after RSurf_PrepareVerticesForBatch
2711                 if (rsurface.batchskeletaltransform3x4)
2712                         permutation |= SHADERPERMUTATION_SKELETAL;
2713                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2714                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2715                 if (mode == SHADERMODE_LIGHTSOURCE)
2716                 {
2717                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2718                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2719                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2720                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2721                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2722                         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);
2723         
2724                         // additive passes are only darkened by fog, not tinted
2725                         if (r_glsl_permutation->loc_FogColor >= 0)
2726                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2727                         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);
2728                 }
2729                 else
2730                 {
2731                         if (mode == SHADERMODE_FLATCOLOR)
2732                         {
2733                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2734                         }
2735                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2736                         {
2737                                 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]);
2738                                 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]);
2739                                 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);
2740                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2741                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2742                                 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]);
2743                                 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]);
2744                         }
2745                         else
2746                         {
2747                                 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]);
2748                                 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]);
2749                                 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);
2750                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2751                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2752                         }
2753                         // additive passes are only darkened by fog, not tinted
2754                         if (r_glsl_permutation->loc_FogColor >= 0)
2755                         {
2756                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2757                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2758                                 else
2759                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2760                         }
2761                         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);
2762                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2763                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2764                         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]);
2765                         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]);
2766                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2767                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2768                         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);
2769                         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]);
2770                 }
2771                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2772                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2773                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2774                 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]);
2775                 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]);
2776
2777                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2778                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2779                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2780                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2781                 {
2782                         if (rsurface.texture->pantstexture)
2783                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2784                         else
2785                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2786                 }
2787                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2788                 {
2789                         if (rsurface.texture->shirttexture)
2790                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2791                         else
2792                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2793                 }
2794                 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]);
2795                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2796                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2797                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2798                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2799                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2800                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2801                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2802                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2803                         );
2804                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2805                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2806                 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]);
2807                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2808                 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);}
2809                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2810
2811                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2812                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2813                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2814                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2815                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2816                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2817                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2818                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2819                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2820                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2821                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2822                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2823                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2824                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2825                 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);
2826                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2827                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2828                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2829                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2830                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2831                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2832                 {
2833                         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);
2834                         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);
2835                         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);
2836                 }
2837                 else
2838                 {
2839                         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);
2840                 }
2841                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2842                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2843                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2844                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2845                 {
2846                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2847                         if (rsurface.rtlight)
2848                         {
2849                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2850                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2851                         }
2852                 }
2853                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2854                 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
2855                         qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
2856                 CHECKGLERROR
2857                 break;
2858         case RENDERPATH_GL11:
2859         case RENDERPATH_GL13:
2860         case RENDERPATH_GLES1:
2861                 break;
2862         case RENDERPATH_SOFT:
2863                 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2864                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2865                 R_SetupShader_SetPermutationSoft(mode, permutation);
2866                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2867                 if (mode == SHADERMODE_LIGHTSOURCE)
2868                 {
2869                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2870                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2871                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2872                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2873                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2874                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2875         
2876                         // additive passes are only darkened by fog, not tinted
2877                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2878                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2879                 }
2880                 else
2881                 {
2882                         if (mode == SHADERMODE_FLATCOLOR)
2883                         {
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2885                         }
2886                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2887                         {
2888                                 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]);
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2891                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2893                                 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]);
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2895                         }
2896                         else
2897                         {
2898                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2900                                 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);
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2903                         }
2904                         // additive passes are only darkened by fog, not tinted
2905                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2907                         else
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2909                         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);
2910                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2911                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2912                         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]);
2913                         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]);
2914                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2915                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2916                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2917                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2918                 }
2919                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2920                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2921                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2922                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2923                 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]);
2924
2925                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2926                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2927                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2928                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2929                 {
2930                         if (rsurface.texture->pantstexture)
2931                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2932                         else
2933                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2934                 }
2935                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2936                 {
2937                         if (rsurface.texture->shirttexture)
2938                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2939                         else
2940                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2941                 }
2942                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2943                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2944                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2945                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2946                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2947                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2948                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2949                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2950                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2951                         );
2952                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2953                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2954                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2955                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2956
2957                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2958                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2959                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2960                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2961                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2962                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2963                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2964                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2965                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2966                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2967                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2968                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2969                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2970                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2971                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2972                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2973                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2974                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2975                 {
2976                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2977                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2978                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2979                 }
2980                 else
2981                 {
2982                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2983                 }
2984 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2985                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2986                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2987                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2988                 {
2989                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2990                         if (rsurface.rtlight)
2991                         {
2992                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2993                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2994                         }
2995                 }
2996                 break;
2997         }
2998 }
2999
3000 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3001 {
3002         // select a permutation of the lighting shader appropriate to this
3003         // combination of texture, entity, light source, and fogging, only use the
3004         // minimum features necessary to avoid wasting rendering time in the
3005         // fragment shader on features that are not being used
3006         unsigned int permutation = 0;
3007         unsigned int mode = 0;
3008         const float *lightcolorbase = rtlight->currentcolor;
3009         float ambientscale = rtlight->ambientscale;
3010         float diffusescale = rtlight->diffusescale;
3011         float specularscale = rtlight->specularscale;
3012         // this is the location of the light in view space
3013         vec3_t viewlightorigin;
3014         // this transforms from view space (camera) to light space (cubemap)
3015         matrix4x4_t viewtolight;
3016         matrix4x4_t lighttoview;
3017         float viewtolight16f[16];
3018         // light source
3019         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3020         if (rtlight->currentcubemap != r_texture_whitecube)
3021                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3022         if (diffusescale > 0)
3023                 permutation |= SHADERPERMUTATION_DIFFUSE;
3024         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3025                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3026         if (r_shadow_usingshadowmap2d)
3027         {
3028                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3029                 if (r_shadow_shadowmapvsdct)
3030                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3031
3032                 if (r_shadow_shadowmap2ddepthbuffer)
3033                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3034         }
3035         if (vid.allowalphatocoverage)
3036                 GL_AlphaToCoverage(false);
3037         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3038         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3039         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3040         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3041         switch(vid.renderpath)
3042         {
3043         case RENDERPATH_D3D9:
3044 #ifdef SUPPORTD3D
3045                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3046                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3047                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3048                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3049                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3050                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3051                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3052                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3053                 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);
3054                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3055                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3056
3057                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3058                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3059                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3060                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3061                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3062 #endif
3063                 break;
3064         case RENDERPATH_D3D10:
3065                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3066                 break;
3067         case RENDERPATH_D3D11:
3068                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3069                 break;
3070         case RENDERPATH_GL20:
3071         case RENDERPATH_GLES2:
3072                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3073                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3074                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3075                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3076                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3077                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3078                 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]);
3079                 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]);
3080                 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);
3081                 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]);
3082                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3083
3084                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
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_shadowmap2ddepthtexture                    );
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 , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3099                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3100                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
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_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3109                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3110                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3111                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3112                 break;
3113         }
3114 }
3115
3116 #define SKINFRAME_HASH 1024
3117
3118 typedef struct
3119 {
3120         int loadsequence; // incremented each level change
3121         memexpandablearray_t array;
3122         skinframe_t *hash[SKINFRAME_HASH];
3123 }
3124 r_skinframe_t;
3125 r_skinframe_t r_skinframe;
3126
3127 void R_SkinFrame_PrepareForPurge(void)
3128 {
3129         r_skinframe.loadsequence++;
3130         // wrap it without hitting zero
3131         if (r_skinframe.loadsequence >= 200)
3132                 r_skinframe.loadsequence = 1;
3133 }
3134
3135 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3136 {
3137         if (!skinframe)
3138                 return;
3139         // mark the skinframe as used for the purging code
3140         skinframe->loadsequence = r_skinframe.loadsequence;
3141 }
3142
3143 void R_SkinFrame_Purge(void)
3144 {
3145         int i;
3146         skinframe_t *s;
3147         for (i = 0;i < SKINFRAME_HASH;i++)
3148         {
3149                 for (s = r_skinframe.hash[i];s;s = s->next)
3150                 {
3151                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3152                         {
3153                                 if (s->merged == s->base)
3154                                         s->merged = NULL;
3155                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3156                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3157                                 R_PurgeTexture(s->merged);s->merged = NULL;
3158                                 R_PurgeTexture(s->base  );s->base   = NULL;
3159                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3160                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3161                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3162                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3163                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3164                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3165                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3166                                 s->loadsequence = 0;
3167                         }
3168                 }
3169         }
3170 }
3171
3172 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3173         skinframe_t *item;
3174         char basename[MAX_QPATH];
3175
3176         Image_StripImageExtension(name, basename, sizeof(basename));
3177
3178         if( last == NULL ) {
3179                 int hashindex;
3180                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3181                 item = r_skinframe.hash[hashindex];
3182         } else {
3183                 item = last->next;
3184         }
3185
3186         // linearly search through the hash bucket
3187         for( ; item ; item = item->next ) {
3188                 if( !strcmp( item->basename, basename ) ) {
3189                         return item;
3190                 }
3191         }
3192         return NULL;
3193 }
3194
3195 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3196 {
3197         skinframe_t *item;
3198         int hashindex;
3199         char basename[MAX_QPATH];
3200
3201         Image_StripImageExtension(name, basename, sizeof(basename));
3202
3203         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3204         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3205                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3206                         break;
3207
3208         if (!item) {
3209                 rtexture_t *dyntexture;
3210                 // check whether its a dynamic texture
3211                 dyntexture = CL_GetDynTexture( basename );
3212                 if (!add && !dyntexture)
3213                         return NULL;
3214                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3215                 memset(item, 0, sizeof(*item));
3216                 strlcpy(item->basename, basename, sizeof(item->basename));
3217                 item->base = dyntexture; // either NULL or dyntexture handle
3218                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3219                 item->comparewidth = comparewidth;
3220                 item->compareheight = compareheight;
3221                 item->comparecrc = comparecrc;
3222                 item->next = r_skinframe.hash[hashindex];
3223                 r_skinframe.hash[hashindex] = item;
3224         }
3225         else if (textureflags & TEXF_FORCE_RELOAD)
3226         {
3227                 rtexture_t *dyntexture;
3228                 // check whether its a dynamic texture
3229                 dyntexture = CL_GetDynTexture( basename );
3230                 if (!add && !dyntexture)
3231                         return NULL;
3232                 if (item->merged == item->base)
3233                         item->merged = NULL;
3234                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3235                 R_PurgeTexture(item->stain );item->stain  = NULL;
3236                 R_PurgeTexture(item->merged);item->merged = NULL;
3237                 R_PurgeTexture(item->base  );item->base   = NULL;
3238                 R_PurgeTexture(item->pants );item->pants  = NULL;
3239                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3240                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3241                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3242                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3243                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3244         R_PurgeTexture(item->reflect);item->reflect = NULL;
3245                 item->loadsequence = 0;
3246         }
3247         else if( item->base == NULL )
3248         {
3249                 rtexture_t *dyntexture;
3250                 // check whether its a dynamic texture
3251                 // 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]
3252                 dyntexture = CL_GetDynTexture( basename );
3253                 item->base = dyntexture; // either NULL or dyntexture handle
3254         }
3255
3256         R_SkinFrame_MarkUsed(item);
3257         return item;
3258 }
3259
3260 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3261         { \
3262                 unsigned long long avgcolor[5], wsum; \
3263                 int pix, comp, w; \
3264                 avgcolor[0] = 0; \
3265                 avgcolor[1] = 0; \
3266                 avgcolor[2] = 0; \
3267                 avgcolor[3] = 0; \
3268                 avgcolor[4] = 0; \
3269                 wsum = 0; \
3270                 for(pix = 0; pix < cnt; ++pix) \
3271                 { \
3272                         w = 0; \
3273                         for(comp = 0; comp < 3; ++comp) \
3274                                 w += getpixel; \
3275                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3276                         { \
3277                                 ++wsum; \
3278                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3279                                 w = getpixel; \
3280                                 for(comp = 0; comp < 3; ++comp) \
3281                                         avgcolor[comp] += getpixel * w; \
3282                                 avgcolor[3] += w; \
3283                         } \
3284                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3285                         avgcolor[4] += getpixel; \
3286                 } \
3287                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3288                         avgcolor[3] = 1; \
3289                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3290                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3291                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3292                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3293         }
3294
3295 extern cvar_t gl_picmip;
3296 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3297 {
3298         int j;
3299         unsigned char *pixels;
3300         unsigned char *bumppixels;
3301         unsigned char *basepixels = NULL;
3302         int basepixels_width = 0;
3303         int basepixels_height = 0;
3304         skinframe_t *skinframe;
3305         rtexture_t *ddsbase = NULL;
3306         qboolean ddshasalpha = false;
3307         float ddsavgcolor[4];
3308         char basename[MAX_QPATH];
3309         int miplevel = R_PicmipForFlags(textureflags);
3310         int savemiplevel = miplevel;
3311         int mymiplevel;
3312         char vabuf[1024];
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(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
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(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
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(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
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(vabuf, sizeof(vabuf), "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(vabuf, sizeof(vabuf), "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(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3409                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3410                 if (r_loadgloss)
3411                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3412                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3413                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3414                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
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(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3422                 {
3423                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3424                         Mem_Free(pixels);
3425                         pixels = NULL;
3426                 }
3427                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%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(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
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(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3440                         Mem_Free(pixels);
3441                 }
3442 #ifndef USE_GLES2
3443                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3444                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "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(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3452         {
3453                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3454 #ifndef USE_GLES2
3455                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3456                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "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(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3463         {
3464                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3465 #ifndef USE_GLES2
3466                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3467                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "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(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3475         {
3476                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3477 #ifndef USE_GLES2
3478                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3479                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "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(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3487         {
3488                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3489 #ifndef USE_GLES2
3490                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3491                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "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(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3499         {
3500                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3501 #ifndef USE_GLES2
3502                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3503                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "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         char vabuf[1024];
3522
3523         if (cls.state == ca_dedicated)
3524                 return NULL;
3525
3526         // if already loaded just return it, otherwise make a new skinframe
3527         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3528         if (skinframe->base)
3529                 return skinframe;
3530         textureflags &= ~TEXF_FORCE_RELOAD;
3531
3532         skinframe->stain = NULL;
3533         skinframe->merged = NULL;
3534         skinframe->base = NULL;
3535         skinframe->pants = NULL;
3536         skinframe->shirt = NULL;
3537         skinframe->nmap = NULL;
3538         skinframe->gloss = NULL;
3539         skinframe->glow = NULL;
3540         skinframe->fog = NULL;
3541         skinframe->reflect = NULL;
3542         skinframe->hasalpha = false;
3543
3544         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3545         if (!skindata)
3546                 return NULL;
3547
3548         if (developer_loading.integer)
3549                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3550
3551         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3552         {
3553                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3554                 temp2 = temp1 + width * height * 4;
3555                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3556                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3557                 Mem_Free(temp1);
3558         }
3559         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3560         if (textureflags & TEXF_ALPHA)
3561         {
3562                 for (i = 3;i < width * height * 4;i += 4)
3563                 {
3564                         if (skindata[i] < 255)
3565                         {
3566                                 skinframe->hasalpha = true;
3567                                 break;
3568                         }
3569                 }
3570                 if (r_loadfog && skinframe->hasalpha)
3571                 {
3572                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3573                         memcpy(fogpixels, skindata, width * height * 4);
3574                         for (i = 0;i < width * height * 4;i += 4)
3575                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3576                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3577                         Mem_Free(fogpixels);
3578                 }
3579         }
3580
3581         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3582         //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]);
3583
3584         return skinframe;
3585 }
3586
3587 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3588 {
3589         int i;
3590         int featuresmask;
3591         skinframe_t *skinframe;
3592
3593         if (cls.state == ca_dedicated)
3594                 return NULL;
3595
3596         // if already loaded just return it, otherwise make a new skinframe
3597         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3598         if (skinframe->base)
3599                 return skinframe;
3600         //textureflags &= ~TEXF_FORCE_RELOAD;
3601
3602         skinframe->stain = NULL;
3603         skinframe->merged = NULL;
3604         skinframe->base = NULL;
3605         skinframe->pants = NULL;
3606         skinframe->shirt = NULL;
3607         skinframe->nmap = NULL;
3608         skinframe->gloss = NULL;
3609         skinframe->glow = NULL;
3610         skinframe->fog = NULL;
3611         skinframe->reflect = NULL;
3612         skinframe->hasalpha = false;
3613
3614         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3615         if (!skindata)
3616                 return NULL;
3617
3618         if (developer_loading.integer)
3619                 Con_Printf("loading quake skin \"%s\"\n", name);
3620
3621         // 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)
3622         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3623         memcpy(skinframe->qpixels, skindata, width*height);
3624         skinframe->qwidth = width;
3625         skinframe->qheight = height;
3626
3627         featuresmask = 0;
3628         for (i = 0;i < width * height;i++)
3629                 featuresmask |= palette_featureflags[skindata[i]];
3630
3631         skinframe->hasalpha = false;
3632         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3633         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3634         skinframe->qgeneratemerged = true;
3635         skinframe->qgeneratebase = skinframe->qhascolormapping;
3636         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3637
3638         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3639         //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]);
3640
3641         return skinframe;
3642 }
3643
3644 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3645 {
3646         int width;
3647         int height;
3648         unsigned char *skindata;
3649         char vabuf[1024];
3650
3651         if (!skinframe->qpixels)
3652                 return;
3653
3654         if (!skinframe->qhascolormapping)
3655                 colormapped = false;
3656
3657         if (colormapped)
3658         {
3659                 if (!skinframe->qgeneratebase)
3660                         return;
3661         }
3662         else
3663         {
3664                 if (!skinframe->qgeneratemerged)
3665                         return;
3666         }
3667
3668         width = skinframe->qwidth;
3669         height = skinframe->qheight;
3670         skindata = skinframe->qpixels;
3671
3672         if (skinframe->qgeneratenmap)
3673         {
3674                 unsigned char *temp1, *temp2;
3675                 skinframe->qgeneratenmap = false;
3676                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3677                 temp2 = temp1 + width * height * 4;
3678                 // use either a custom palette or the quake palette
3679                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3680                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3681                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3682                 Mem_Free(temp1);
3683         }
3684
3685         if (skinframe->qgenerateglow)
3686         {
3687                 skinframe->qgenerateglow = false;
3688                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3689         }
3690
3691         if (colormapped)
3692         {
3693                 skinframe->qgeneratebase = false;
3694                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3695                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3696                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3697         }
3698         else
3699         {
3700                 skinframe->qgeneratemerged = false;
3701                 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);
3702         }
3703
3704         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3705         {
3706                 Mem_Free(skinframe->qpixels);
3707                 skinframe->qpixels = NULL;
3708         }
3709 }
3710
3711 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)
3712 {
3713         int i;
3714         skinframe_t *skinframe;
3715         char vabuf[1024];
3716
3717         if (cls.state == ca_dedicated)
3718                 return NULL;
3719
3720         // if already loaded just return it, otherwise make a new skinframe
3721         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3722         if (skinframe->base)
3723                 return skinframe;
3724         textureflags &= ~TEXF_FORCE_RELOAD;
3725
3726         skinframe->stain = NULL;
3727         skinframe->merged = NULL;
3728         skinframe->base = NULL;
3729         skinframe->pants = NULL;
3730         skinframe->shirt = NULL;
3731         skinframe->nmap = NULL;
3732         skinframe->gloss = NULL;
3733         skinframe->glow = NULL;
3734         skinframe->fog = NULL;
3735         skinframe->reflect = NULL;
3736         skinframe->hasalpha = false;
3737
3738         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3739         if (!skindata)
3740                 return NULL;
3741
3742         if (developer_loading.integer)
3743                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3744
3745         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3746         if (textureflags & TEXF_ALPHA)
3747         {
3748                 for (i = 0;i < width * height;i++)
3749                 {
3750                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3751                         {
3752                                 skinframe->hasalpha = true;
3753                                 break;
3754                         }
3755                 }
3756                 if (r_loadfog && skinframe->hasalpha)
3757                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3758         }
3759
3760         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3761         //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]);
3762
3763         return skinframe;
3764 }
3765
3766 skinframe_t *R_SkinFrame_LoadMissing(void)
3767 {
3768         skinframe_t *skinframe;
3769
3770         if (cls.state == ca_dedicated)
3771                 return NULL;
3772
3773         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3774         skinframe->stain = NULL;
3775         skinframe->merged = NULL;
3776         skinframe->base = NULL;
3777         skinframe->pants = NULL;
3778         skinframe->shirt = NULL;
3779         skinframe->nmap = NULL;
3780         skinframe->gloss = NULL;
3781         skinframe->glow = NULL;
3782         skinframe->fog = NULL;
3783         skinframe->reflect = NULL;
3784         skinframe->hasalpha = false;
3785
3786         skinframe->avgcolor[0] = rand() / RAND_MAX;
3787         skinframe->avgcolor[1] = rand() / RAND_MAX;
3788         skinframe->avgcolor[2] = rand() / RAND_MAX;
3789         skinframe->avgcolor[3] = 1;
3790
3791         return skinframe;
3792 }
3793
3794 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3795 typedef struct suffixinfo_s
3796 {
3797         const char *suffix;
3798         qboolean flipx, flipy, flipdiagonal;
3799 }
3800 suffixinfo_t;
3801 static suffixinfo_t suffix[3][6] =
3802 {
3803         {
3804                 {"px",   false, false, false},
3805                 {"nx",   false, false, false},
3806                 {"py",   false, false, false},
3807                 {"ny",   false, false, false},
3808                 {"pz",   false, false, false},
3809                 {"nz",   false, false, false}
3810         },
3811         {
3812                 {"posx", false, false, false},
3813                 {"negx", false, false, false},
3814                 {"posy", false, false, false},
3815                 {"negy", false, false, false},
3816                 {"posz", false, false, false},
3817                 {"negz", false, false, false}
3818         },
3819         {
3820                 {"rt",    true, false,  true},
3821                 {"lf",   false,  true,  true},
3822                 {"ft",    true,  true, false},
3823                 {"bk",   false, false, false},
3824                 {"up",    true, false,  true},
3825                 {"dn",    true, false,  true}
3826         }
3827 };
3828
3829 static int componentorder[4] = {0, 1, 2, 3};
3830
3831 static rtexture_t *R_LoadCubemap(const char *basename)
3832 {
3833         int i, j, cubemapsize;
3834         unsigned char *cubemappixels, *image_buffer;
3835         rtexture_t *cubemaptexture;
3836         char name[256];
3837         // must start 0 so the first loadimagepixels has no requested width/height
3838         cubemapsize = 0;
3839         cubemappixels = NULL;
3840         cubemaptexture = NULL;
3841         // keep trying different suffix groups (posx, px, rt) until one loads
3842         for (j = 0;j < 3 && !cubemappixels;j++)
3843         {
3844                 // load the 6 images in the suffix group
3845                 for (i = 0;i < 6;i++)
3846                 {
3847                         // generate an image name based on the base and and suffix
3848                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3849                         // load it
3850                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3851                         {
3852                                 // an image loaded, make sure width and height are equal
3853                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3854                                 {
3855                                         // if this is the first image to load successfully, allocate the cubemap memory
3856                                         if (!cubemappixels && image_width >= 1)
3857                                         {
3858                                                 cubemapsize = image_width;
3859                                                 // note this clears to black, so unavailable sides are black
3860                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3861                                         }
3862                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3863                                         if (cubemappixels)
3864                                                 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);
3865                                 }
3866                                 else
3867                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3868                                 // free the image
3869                                 Mem_Free(image_buffer);
3870                         }
3871                 }
3872         }
3873         // if a cubemap loaded, upload it
3874         if (cubemappixels)
3875         {
3876                 if (developer_loading.integer)
3877                         Con_Printf("loading cubemap \"%s\"\n", basename);
3878
3879                 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);
3880                 Mem_Free(cubemappixels);
3881         }
3882         else
3883         {
3884                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3885                 if (developer_loading.integer)
3886                 {
3887                         Con_Printf("(tried tried images ");
3888                         for (j = 0;j < 3;j++)
3889                                 for (i = 0;i < 6;i++)
3890                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3891                         Con_Print(" and was unable to find any of them).\n");
3892                 }
3893         }
3894         return cubemaptexture;
3895 }
3896
3897 rtexture_t *R_GetCubemap(const char *basename)
3898 {
3899         int i;
3900         for (i = 0;i < r_texture_numcubemaps;i++)
3901                 if (r_texture_cubemaps[i] != NULL)
3902                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3903                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3904         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3905                 return r_texture_whitecube;
3906         r_texture_numcubemaps++;
3907         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3908         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3909         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3910         return r_texture_cubemaps[i]->texture;
3911 }
3912
3913 static void R_Main_FreeViewCache(void)
3914 {
3915         if (r_refdef.viewcache.entityvisible)
3916                 Mem_Free(r_refdef.viewcache.entityvisible);
3917         if (r_refdef.viewcache.world_pvsbits)
3918                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3919         if (r_refdef.viewcache.world_leafvisible)
3920                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3921         if (r_refdef.viewcache.world_surfacevisible)
3922                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3923         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3924 }
3925
3926 static void R_Main_ResizeViewCache(void)
3927 {
3928         int numentities = r_refdef.scene.numentities;
3929         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3930         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3931         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3932         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3933         if (r_refdef.viewcache.maxentities < numentities)
3934         {
3935                 r_refdef.viewcache.maxentities = numentities;
3936                 if (r_refdef.viewcache.entityvisible)
3937                         Mem_Free(r_refdef.viewcache.entityvisible);
3938                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3939         }
3940         if (r_refdef.viewcache.world_numclusters != numclusters)
3941         {
3942                 r_refdef.viewcache.world_numclusters = numclusters;
3943                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3944                 if (r_refdef.viewcache.world_pvsbits)
3945                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3946                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3947         }
3948         if (r_refdef.viewcache.world_numleafs != numleafs)
3949         {
3950                 r_refdef.viewcache.world_numleafs = numleafs;
3951                 if (r_refdef.viewcache.world_leafvisible)
3952                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3953                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3954         }
3955         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3956         {
3957                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3958                 if (r_refdef.viewcache.world_surfacevisible)
3959                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3960                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3961         }
3962 }
3963
3964 extern rtexture_t *loadingscreentexture;
3965 static void gl_main_start(void)
3966 {
3967         loadingscreentexture = NULL;
3968         r_texture_blanknormalmap = NULL;
3969         r_texture_white = NULL;
3970         r_texture_grey128 = NULL;
3971         r_texture_black = NULL;
3972         r_texture_whitecube = NULL;
3973         r_texture_normalizationcube = NULL;
3974         r_texture_fogattenuation = NULL;
3975         r_texture_fogheighttexture = NULL;
3976         r_texture_gammaramps = NULL;
3977         r_texture_numcubemaps = 0;
3978
3979         r_loaddds = r_texture_dds_load.integer != 0;
3980         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3981
3982         switch(vid.renderpath)
3983         {
3984         case RENDERPATH_GL20:
3985         case RENDERPATH_D3D9:
3986         case RENDERPATH_D3D10:
3987         case RENDERPATH_D3D11:
3988         case RENDERPATH_SOFT:
3989         case RENDERPATH_GLES2:
3990                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3991                 Cvar_SetValueQuick(&gl_combine, 1);
3992                 Cvar_SetValueQuick(&r_glsl, 1);
3993                 r_loadnormalmap = true;
3994                 r_loadgloss = true;
3995                 r_loadfog = false;
3996                 break;
3997         case RENDERPATH_GL13:
3998         case RENDERPATH_GLES1:
3999                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4000                 Cvar_SetValueQuick(&gl_combine, 1);
4001                 Cvar_SetValueQuick(&r_glsl, 0);
4002                 r_loadnormalmap = false;
4003                 r_loadgloss = false;
4004                 r_loadfog = true;
4005                 break;
4006         case RENDERPATH_GL11:
4007                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4008                 Cvar_SetValueQuick(&gl_combine, 0);
4009                 Cvar_SetValueQuick(&r_glsl, 0);
4010                 r_loadnormalmap = false;
4011                 r_loadgloss = false;
4012                 r_loadfog = true;
4013                 break;
4014         }
4015
4016         R_AnimCache_Free();
4017         R_FrameData_Reset();
4018
4019         r_numqueries = 0;
4020         r_maxqueries = 0;
4021         memset(r_queries, 0, sizeof(r_queries));
4022
4023         r_qwskincache = NULL;
4024         r_qwskincache_size = 0;
4025
4026         // due to caching of texture_t references, the collision cache must be reset
4027         Collision_Cache_Reset(true);
4028
4029         // set up r_skinframe loading system for textures
4030         memset(&r_skinframe, 0, sizeof(r_skinframe));
4031         r_skinframe.loadsequence = 1;
4032         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4033
4034         r_main_texturepool = R_AllocTexturePool();
4035         R_BuildBlankTextures();
4036         R_BuildNoTexture();
4037         if (vid.support.arb_texture_cube_map)
4038         {
4039                 R_BuildWhiteCube();
4040                 R_BuildNormalizationCube();
4041         }
4042         r_texture_fogattenuation = NULL;
4043         r_texture_fogheighttexture = NULL;
4044         r_texture_gammaramps = NULL;
4045         //r_texture_fogintensity = NULL;
4046         memset(&r_fb, 0, sizeof(r_fb));
4047         r_glsl_permutation = NULL;
4048         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4049         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4050         glslshaderstring = NULL;
4051 #ifdef SUPPORTD3D
4052         r_hlsl_permutation = NULL;
4053         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4054         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4055 #endif
4056         hlslshaderstring = NULL;
4057         memset(&r_svbsp, 0, sizeof (r_svbsp));
4058
4059         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4060         r_texture_numcubemaps = 0;
4061
4062         r_refdef.fogmasktable_density = 0;
4063 }
4064
4065 static void gl_main_shutdown(void)
4066 {
4067         R_AnimCache_Free();
4068         R_FrameData_Reset();
4069
4070         R_Main_FreeViewCache();
4071
4072         switch(vid.renderpath)
4073         {
4074         case RENDERPATH_GL11:
4075         case RENDERPATH_GL13:
4076         case RENDERPATH_GL20:
4077         case RENDERPATH_GLES1:
4078         case RENDERPATH_GLES2:
4079 #ifdef GL_SAMPLES_PASSED_ARB
4080                 if (r_maxqueries)
4081                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4082 #endif
4083                 break;
4084         case RENDERPATH_D3D9:
4085                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4086                 break;
4087         case RENDERPATH_D3D10:
4088                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4089                 break;
4090         case RENDERPATH_D3D11:
4091                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4092                 break;
4093         case RENDERPATH_SOFT:
4094                 break;
4095         }
4096
4097         r_numqueries = 0;
4098         r_maxqueries = 0;
4099         memset(r_queries, 0, sizeof(r_queries));
4100
4101         r_qwskincache = NULL;
4102         r_qwskincache_size = 0;
4103
4104         // clear out the r_skinframe state
4105         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4106         memset(&r_skinframe, 0, sizeof(r_skinframe));
4107
4108         if (r_svbsp.nodes)
4109                 Mem_Free(r_svbsp.nodes);
4110         memset(&r_svbsp, 0, sizeof (r_svbsp));
4111         R_FreeTexturePool(&r_main_texturepool);
4112         loadingscreentexture = NULL;
4113         r_texture_blanknormalmap = NULL;
4114         r_texture_white = NULL;
4115         r_texture_grey128 = NULL;
4116         r_texture_black = NULL;
4117         r_texture_whitecube = NULL;
4118         r_texture_normalizationcube = NULL;
4119         r_texture_fogattenuation = NULL;
4120         r_texture_fogheighttexture = NULL;
4121         r_texture_gammaramps = NULL;
4122         r_texture_numcubemaps = 0;
4123         //r_texture_fogintensity = NULL;
4124         memset(&r_fb, 0, sizeof(r_fb));
4125         R_GLSL_Restart_f();
4126
4127         r_glsl_permutation = NULL;
4128         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4129         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4130         glslshaderstring = NULL;
4131 #ifdef SUPPORTD3D
4132         r_hlsl_permutation = NULL;
4133         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4134         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4135 #endif
4136         hlslshaderstring = NULL;
4137 }
4138
4139 static void gl_main_newmap(void)
4140 {
4141         // FIXME: move this code to client
4142         char *entities, entname[MAX_QPATH];
4143         if (r_qwskincache)
4144                 Mem_Free(r_qwskincache);
4145         r_qwskincache = NULL;
4146         r_qwskincache_size = 0;
4147         if (cl.worldmodel)
4148         {
4149                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4150                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4151                 {
4152                         CL_ParseEntityLump(entities);
4153                         Mem_Free(entities);
4154                         return;
4155                 }
4156                 if (cl.worldmodel->brush.entities)
4157                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4158         }
4159         R_Main_FreeViewCache();
4160
4161         R_FrameData_Reset();
4162 }
4163
4164 void GL_Main_Init(void)
4165 {
4166         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4167
4168         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4169         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4170         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4171         if (gamemode == GAME_NEHAHRA)
4172         {
4173                 Cvar_RegisterVariable (&gl_fogenable);
4174                 Cvar_RegisterVariable (&gl_fogdensity);
4175                 Cvar_RegisterVariable (&gl_fogred);
4176                 Cvar_RegisterVariable (&gl_foggreen);
4177                 Cvar_RegisterVariable (&gl_fogblue);
4178                 Cvar_RegisterVariable (&gl_fogstart);
4179                 Cvar_RegisterVariable (&gl_fogend);
4180                 Cvar_RegisterVariable (&gl_skyclip);
4181         }
4182         Cvar_RegisterVariable(&r_motionblur);
4183         Cvar_RegisterVariable(&r_damageblur);
4184         Cvar_RegisterVariable(&r_motionblur_averaging);
4185         Cvar_RegisterVariable(&r_motionblur_randomize);
4186         Cvar_RegisterVariable(&r_motionblur_minblur);
4187         Cvar_RegisterVariable(&r_motionblur_maxblur);
4188         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4189         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4190         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4191         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4192         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4193         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4194         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4195         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4196         Cvar_RegisterVariable(&r_equalize_entities_by);
4197         Cvar_RegisterVariable(&r_equalize_entities_to);
4198         Cvar_RegisterVariable(&r_depthfirst);
4199         Cvar_RegisterVariable(&r_useinfinitefarclip);
4200         Cvar_RegisterVariable(&r_farclip_base);
4201         Cvar_RegisterVariable(&r_farclip_world);
4202         Cvar_RegisterVariable(&r_nearclip);
4203         Cvar_RegisterVariable(&r_deformvertexes);
4204         Cvar_RegisterVariable(&r_transparent);
4205         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4206         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4207         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4208         Cvar_RegisterVariable(&r_showoverdraw);
4209         Cvar_RegisterVariable(&r_showbboxes);
4210         Cvar_RegisterVariable(&r_showsurfaces);
4211         Cvar_RegisterVariable(&r_showtris);
4212         Cvar_RegisterVariable(&r_shownormals);
4213         Cvar_RegisterVariable(&r_showlighting);
4214         Cvar_RegisterVariable(&r_showshadowvolumes);
4215         Cvar_RegisterVariable(&r_showcollisionbrushes);
4216         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4217         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4218         Cvar_RegisterVariable(&r_showdisabledepthtest);
4219         Cvar_RegisterVariable(&r_drawportals);
4220         Cvar_RegisterVariable(&r_drawentities);
4221         Cvar_RegisterVariable(&r_draw2d);
4222         Cvar_RegisterVariable(&r_drawworld);
4223         Cvar_RegisterVariable(&r_cullentities_trace);
4224         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4225         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4226         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4227         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4228         Cvar_RegisterVariable(&r_sortentities);
4229         Cvar_RegisterVariable(&r_drawviewmodel);
4230         Cvar_RegisterVariable(&r_drawexteriormodel);
4231         Cvar_RegisterVariable(&r_speeds);
4232         Cvar_RegisterVariable(&r_fullbrights);
4233         Cvar_RegisterVariable(&r_wateralpha);
4234         Cvar_RegisterVariable(&r_dynamic);
4235         Cvar_RegisterVariable(&r_fakelight);
4236         Cvar_RegisterVariable(&r_fakelight_intensity);
4237         Cvar_RegisterVariable(&r_fullbright);
4238         Cvar_RegisterVariable(&r_shadows);
4239         Cvar_RegisterVariable(&r_shadows_darken);
4240         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4241         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4242         Cvar_RegisterVariable(&r_shadows_throwdistance);
4243         Cvar_RegisterVariable(&r_shadows_throwdirection);
4244         Cvar_RegisterVariable(&r_shadows_focus);
4245         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4246         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4247         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4248         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4249         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4250         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4251         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4252         Cvar_RegisterVariable(&r_fog_exp2);
4253         Cvar_RegisterVariable(&r_fog_clear);
4254         Cvar_RegisterVariable(&r_drawfog);
4255         Cvar_RegisterVariable(&r_transparentdepthmasking);
4256         Cvar_RegisterVariable(&r_transparent_sortmindist);
4257         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4258         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4259         Cvar_RegisterVariable(&r_texture_dds_load);
4260         Cvar_RegisterVariable(&r_texture_dds_save);
4261         Cvar_RegisterVariable(&r_textureunits);
4262         Cvar_RegisterVariable(&gl_combine);
4263         Cvar_RegisterVariable(&r_usedepthtextures);
4264         Cvar_RegisterVariable(&r_viewfbo);
4265         Cvar_RegisterVariable(&r_viewscale);
4266         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4267         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4268         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4269         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4270         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4271         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4272         Cvar_RegisterVariable(&r_glsl);
4273         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4274         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4275         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4276         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4277         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4278         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4279         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4280         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4281         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4282         Cvar_RegisterVariable(&r_glsl_postprocess);
4283         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4284         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4285         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4286         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4287         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4288         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4289         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4290         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4291         Cvar_RegisterVariable(&r_celshading);
4292         Cvar_RegisterVariable(&r_celoutlines);
4293
4294         Cvar_RegisterVariable(&r_water);
4295         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4296         Cvar_RegisterVariable(&r_water_clippingplanebias);
4297         Cvar_RegisterVariable(&r_water_refractdistort);
4298         Cvar_RegisterVariable(&r_water_reflectdistort);
4299         Cvar_RegisterVariable(&r_water_scissormode);
4300         Cvar_RegisterVariable(&r_water_lowquality);
4301         Cvar_RegisterVariable(&r_water_hideplayer);
4302         Cvar_RegisterVariable(&r_water_fbo);
4303
4304         Cvar_RegisterVariable(&r_lerpsprites);
4305         Cvar_RegisterVariable(&r_lerpmodels);
4306         Cvar_RegisterVariable(&r_lerplightstyles);
4307         Cvar_RegisterVariable(&r_waterscroll);
4308         Cvar_RegisterVariable(&r_bloom);
4309         Cvar_RegisterVariable(&r_bloom_colorscale);
4310         Cvar_RegisterVariable(&r_bloom_brighten);
4311         Cvar_RegisterVariable(&r_bloom_blur);
4312         Cvar_RegisterVariable(&r_bloom_resolution);
4313         Cvar_RegisterVariable(&r_bloom_colorexponent);
4314         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4315         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4316         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4317         Cvar_RegisterVariable(&r_hdr_glowintensity);
4318         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4319         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4320         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4321         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4322         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4323         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4324         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4325         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4326         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4327         Cvar_RegisterVariable(&developer_texturelogging);
4328         Cvar_RegisterVariable(&gl_lightmaps);
4329         Cvar_RegisterVariable(&r_test);
4330         Cvar_RegisterVariable(&r_batch_multidraw);
4331         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4332         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4333         Cvar_RegisterVariable(&r_glsl_skeletal);
4334         Cvar_RegisterVariable(&r_glsl_saturation);
4335         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4336         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4337         Cvar_RegisterVariable(&r_framedatasize);
4338         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4339                 Cvar_SetValue("r_fullbrights", 0);
4340         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4341 }
4342
4343 void Render_Init(void)
4344 {
4345         gl_backend_init();
4346         R_Textures_Init();
4347         GL_Main_Init();
4348         Font_Init();
4349         GL_Draw_Init();
4350         R_Shadow_Init();
4351         R_Sky_Init();
4352         GL_Surf_Init();
4353         Sbar_Init();
4354         R_Particles_Init();
4355         R_Explosion_Init();
4356         R_LightningBeams_Init();
4357         Mod_RenderInit();
4358 }
4359
4360 /*
4361 ===============
4362 GL_Init
4363 ===============
4364 */
4365 #ifndef USE_GLES2
4366 extern char *ENGINE_EXTENSIONS;
4367 void GL_Init (void)
4368 {
4369         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4370         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4371         gl_version = (const char *)qglGetString(GL_VERSION);
4372         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4373
4374         if (!gl_extensions)
4375                 gl_extensions = "";
4376         if (!gl_platformextensions)
4377                 gl_platformextensions = "";
4378
4379         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4380         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4381         Con_Printf("GL_VERSION: %s\n", gl_version);
4382         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4383         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4384
4385         VID_CheckExtensions();
4386
4387         // LordHavoc: report supported extensions
4388         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4389
4390         // clear to black (loading plaque will be seen over this)
4391         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4392 }
4393 #endif
4394
4395 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4396 {
4397         int i;
4398         mplane_t *p;
4399         if (r_trippy.integer)
4400                 return false;
4401         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4402         {
4403                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4404                 if (i == 4)
4405                         continue;
4406                 p = r_refdef.view.frustum + i;
4407                 switch(p->signbits)
4408                 {
4409                 default:
4410                 case 0:
4411                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4412                                 return true;
4413                         break;
4414                 case 1:
4415                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4416                                 return true;
4417                         break;
4418                 case 2:
4419                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4420                                 return true;
4421                         break;
4422                 case 3:
4423                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4424                                 return true;
4425                         break;
4426                 case 4:
4427                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4428                                 return true;
4429                         break;
4430                 case 5:
4431                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4432                                 return true;
4433                         break;
4434                 case 6:
4435                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4436                                 return true;
4437                         break;
4438                 case 7:
4439                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4440                                 return true;
4441                         break;
4442                 }
4443         }
4444         return false;
4445 }
4446
4447 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4448 {
4449         int i;
4450         const mplane_t *p;
4451         if (r_trippy.integer)
4452                 return false;
4453         for (i = 0;i < numplanes;i++)
4454         {
4455                 p = planes + i;
4456                 switch(p->signbits)
4457                 {
4458                 default:
4459                 case 0:
4460                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 1:
4464                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 2:
4468                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 case 3:
4472                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4473                                 return true;
4474                         break;
4475                 case 4:
4476                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4477                                 return true;
4478                         break;
4479                 case 5:
4480                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4481                                 return true;
4482                         break;
4483                 case 6:
4484                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4485                                 return true;
4486                         break;
4487                 case 7:
4488                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4489                                 return true;
4490                         break;
4491                 }
4492         }
4493         return false;
4494 }
4495
4496 //==================================================================================
4497
4498 // LordHavoc: this stores temporary data used within the same frame
4499
4500 typedef struct r_framedata_mem_s
4501 {
4502         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4503         size_t size; // how much usable space
4504         size_t current; // how much space in use
4505         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4506         size_t wantedsize; // how much space was allocated
4507         unsigned char *data; // start of real data (16byte aligned)
4508 }
4509 r_framedata_mem_t;
4510
4511 static r_framedata_mem_t *r_framedata_mem;
4512
4513 void R_FrameData_Reset(void)
4514 {
4515         while (r_framedata_mem)
4516         {
4517                 r_framedata_mem_t *next = r_framedata_mem->purge;
4518                 Mem_Free(r_framedata_mem);
4519                 r_framedata_mem = next;
4520         }
4521 }
4522
4523 static void R_FrameData_Resize(void)
4524 {
4525         size_t wantedsize;
4526         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4527         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4528         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4529         {
4530                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4531                 newmem->wantedsize = wantedsize;
4532                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4533                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4534                 newmem->current = 0;
4535                 newmem->mark = 0;
4536                 newmem->purge = r_framedata_mem;
4537                 r_framedata_mem = newmem;
4538         }
4539 }
4540
4541 void R_FrameData_NewFrame(void)
4542 {
4543         R_FrameData_Resize();
4544         if (!r_framedata_mem)
4545                 return;
4546         // if we ran out of space on the last frame, free the old memory now
4547         while (r_framedata_mem->purge)
4548         {
4549                 // repeatedly remove the second item in the list, leaving only head
4550                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4551                 Mem_Free(r_framedata_mem->purge);
4552                 r_framedata_mem->purge = next;
4553         }
4554         // reset the current mem pointer
4555         r_framedata_mem->current = 0;
4556         r_framedata_mem->mark = 0;
4557 }
4558
4559 void *R_FrameData_Alloc(size_t size)
4560 {
4561         void *data;
4562
4563         // align to 16 byte boundary - the data pointer is already aligned, so we
4564         // only need to ensure the size of every allocation is also aligned
4565         size = (size + 15) & ~15;
4566
4567         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4568         {
4569                 // emergency - we ran out of space, allocate more memory
4570                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4571                 R_FrameData_Resize();
4572         }
4573
4574         data = r_framedata_mem->data + r_framedata_mem->current;
4575         r_framedata_mem->current += size;
4576
4577         // count the usage for stats
4578         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4579         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4580
4581         return (void *)data;
4582 }
4583
4584 void *R_FrameData_Store(size_t size, void *data)
4585 {
4586         void *d = R_FrameData_Alloc(size);
4587         if (d && data)
4588                 memcpy(d, data, size);
4589         return d;
4590 }
4591
4592 void R_FrameData_SetMark(void)
4593 {
4594         if (!r_framedata_mem)
4595                 return;
4596         r_framedata_mem->mark = r_framedata_mem->current;
4597 }
4598
4599 void R_FrameData_ReturnToMark(void)
4600 {
4601         if (!r_framedata_mem)
4602                 return;
4603         r_framedata_mem->current = r_framedata_mem->mark;
4604 }
4605
4606 //==================================================================================
4607
4608 // LordHavoc: animcache originally written by Echon, rewritten since then
4609
4610 /**
4611  * Animation cache prevents re-generating mesh data for an animated model
4612  * multiple times in one frame for lighting, shadowing, reflections, etc.
4613  */
4614
4615 void R_AnimCache_Free(void)
4616 {
4617 }
4618
4619 void R_AnimCache_ClearCache(void)
4620 {
4621         int i;
4622         entity_render_t *ent;
4623
4624         for (i = 0;i < r_refdef.scene.numentities;i++)
4625         {
4626                 ent = r_refdef.scene.entities[i];
4627                 ent->animcache_vertex3f = NULL;
4628                 ent->animcache_normal3f = NULL;
4629                 ent->animcache_svector3f = NULL;
4630                 ent->animcache_tvector3f = NULL;
4631                 ent->animcache_vertexmesh = NULL;
4632                 ent->animcache_vertex3fbuffer = NULL;
4633                 ent->animcache_vertexmeshbuffer = NULL;
4634                 ent->animcache_skeletaltransform3x4 = NULL;
4635         }
4636 }
4637
4638 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4639 {
4640         int i;
4641
4642         // check if we need the meshbuffers
4643         if (!vid.useinterleavedarrays)
4644                 return;
4645
4646         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4647                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4648         // TODO: upload vertex3f buffer?
4649         if (ent->animcache_vertexmesh)
4650         {
4651                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4652                 for (i = 0;i < numvertices;i++)
4653                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4654                 if (ent->animcache_svector3f)
4655                         for (i = 0;i < numvertices;i++)
4656                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4657                 if (ent->animcache_tvector3f)
4658                         for (i = 0;i < numvertices;i++)
4659                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4660                 if (ent->animcache_normal3f)
4661                         for (i = 0;i < numvertices;i++)
4662                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4663                 // TODO: upload vertexmeshbuffer?
4664         }
4665 }
4666
4667 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4668 {
4669         dp_model_t *model = ent->model;
4670         int numvertices;
4671
4672         // cache skeletal animation data first (primarily for gpu-skinning)
4673         if (!ent->animcache_skeletaltransform3x4 && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4674         {
4675                 int i;
4676                 int blends;
4677                 const skeleton_t *skeleton = ent->skeleton;
4678                 const frameblend_t *frameblend = ent->frameblend;
4679                 float *boneposerelative;
4680                 float m[12];
4681                 static float bonepose[256][12];
4682                 ent->animcache_skeletaltransform3x4 = R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4683                 boneposerelative = ent->animcache_skeletaltransform3x4;
4684                 if (skeleton && !skeleton->relativetransforms)
4685                         skeleton = NULL;
4686                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4687                 if (skeleton)
4688                 {
4689                         for (i = 0;i < model->num_bones;i++)
4690                         {
4691                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4692                                 if (model->data_bones[i].parent >= 0)
4693                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4694                                 else
4695                                         memcpy(bonepose[i], m, sizeof(m));
4696
4697                                 // create a relative deformation matrix to describe displacement
4698                                 // from the base mesh, which is used by the actual weighting
4699                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4700                         }
4701                 }
4702                 else
4703                 {
4704                         for (i = 0;i < model->num_bones;i++)
4705                         {
4706                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4707                                 float lerp = frameblend[0].lerp,
4708                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4709                                         rx = pose7s[3] * lerp,
4710                                         ry = pose7s[4] * lerp,
4711                                         rz = pose7s[5] * lerp,
4712                                         rw = pose7s[6] * lerp,
4713                                         dx = tx*rw + ty*rz - tz*ry,
4714                                         dy = -tx*rz + ty*rw + tz*rx,
4715                                         dz = tx*ry - ty*rx + tz*rw,
4716                                         dw = -tx*rx - ty*ry - tz*rz,
4717                                         scale, sx, sy, sz, sw;
4718                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4719                                 {
4720                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4721                                         float lerp = frameblend[blends].lerp,
4722                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4723                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4724                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4725                                         qx *= lerp;
4726                                         qy *= lerp;
4727                                         qz *= lerp;
4728                                         qw *= lerp;
4729                                         rx += qx;
4730                                         ry += qy;
4731                                         rz += qz;
4732                                         rw += qw;
4733                                         dx += tx*qw + ty*qz - tz*qy;
4734                                         dy += -tx*qz + ty*qw + tz*qx;
4735                                         dz += tx*qy - ty*qx + tz*qw;
4736                                         dw += -tx*qx - ty*qy - tz*qz;
4737                                 }
4738                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4739                                 sx = rx * scale;
4740                                 sy = ry * scale;
4741                                 sz = rz * scale;
4742                                 sw = rw * scale;
4743                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4744                                 m[1] = 2*(sx*ry - sw*rz);
4745                                 m[2] = 2*(sx*rz + sw*ry);
4746                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4747                                 m[4] = 2*(sx*ry + sw*rz);
4748                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4749                                 m[6] = 2*(sy*rz - sw*rx);
4750                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4751                                 m[8] = 2*(sx*rz - sw*ry);
4752                                 m[9] = 2*(sy*rz + sw*rx);
4753                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4754                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4755                                 if (i == r_skeletal_debugbone.integer)
4756                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4757                                 m[3] *= r_skeletal_debugtranslatex.value;
4758                                 m[7] *= r_skeletal_debugtranslatey.value;
4759                                 m[11] *= r_skeletal_debugtranslatez.value;
4760                                 if (model->data_bones[i].parent >= 0)
4761                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4762                                 else
4763                                         memcpy(bonepose[i], m, sizeof(m));
4764                                 // create a relative deformation matrix to describe displacement
4765                                 // from the base mesh, which is used by the actual weighting
4766                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4767                         }
4768                 }
4769         }
4770
4771         // see if it's already cached this frame
4772         if (ent->animcache_vertex3f)
4773         {
4774                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4775                 if (wantnormals || wanttangents)
4776                 {
4777                         if (ent->animcache_normal3f)
4778                                 wantnormals = false;
4779                         if (ent->animcache_svector3f)
4780                                 wanttangents = false;
4781                         if (wantnormals || wanttangents)
4782                         {
4783                                 numvertices = model->surfmesh.num_vertices;
4784                                 if (wantnormals)
4785                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4786                                 if (wanttangents)
4787                                 {
4788                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4789                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4790                                 }
4791                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4792                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4793                         }
4794                 }
4795         }
4796         else
4797         {
4798                 // see if this ent is worth caching
4799                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4800                         return false;
4801                 // skip entity if the shader backend has a cheaper way
4802                 if (model->surfmesh.data_skeletalindex4ub && r_glsl_skeletal.integer)
4803                 {
4804                         switch (vid.renderpath)
4805                         {
4806                         case RENDERPATH_GL20:
4807                                 return false;
4808                         case RENDERPATH_GL11:
4809                         case RENDERPATH_GL13:
4810                         case RENDERPATH_GLES1:
4811                         case RENDERPATH_GLES2:
4812                         case RENDERPATH_D3D9:
4813                         case RENDERPATH_D3D10:
4814                         case RENDERPATH_D3D11:
4815                         case RENDERPATH_SOFT:
4816                                 break;
4817                         }
4818                 }
4819                 // get some memory for this entity and generate mesh data
4820                 numvertices = model->surfmesh.num_vertices;
4821                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4822                 if (wantnormals)
4823                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4824                 if (wanttangents)
4825                 {
4826                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4827                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4828                 }
4829                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4830                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4831         }
4832         return true;
4833 }
4834
4835 void R_AnimCache_CacheVisibleEntities(void)
4836 {
4837         int i;
4838         qboolean wantnormals = true;
4839         qboolean wanttangents = !r_showsurfaces.integer;
4840
4841         switch(vid.renderpath)
4842         {
4843         case RENDERPATH_GL20:
4844         case RENDERPATH_D3D9:
4845         case RENDERPATH_D3D10:
4846         case RENDERPATH_D3D11:
4847         case RENDERPATH_GLES2:
4848                 break;
4849         case RENDERPATH_GL11:
4850         case RENDERPATH_GL13:
4851         case RENDERPATH_GLES1:
4852                 wanttangents = false;
4853                 break;
4854         case RENDERPATH_SOFT:
4855                 break;
4856         }
4857
4858         if (r_shownormals.integer)
4859                 wanttangents = wantnormals = true;
4860
4861         // TODO: thread this
4862         // NOTE: R_PrepareRTLights() also caches entities
4863
4864         for (i = 0;i < r_refdef.scene.numentities;i++)
4865                 if (r_refdef.viewcache.entityvisible[i])
4866                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4867 }
4868
4869 //==================================================================================
4870
4871 extern cvar_t r_overheadsprites_pushback;
4872
4873 static void R_View_UpdateEntityLighting (void)
4874 {
4875         int i;
4876         entity_render_t *ent;
4877         vec3_t tempdiffusenormal, avg;
4878         vec_t f, fa, fd, fdd;
4879         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4880
4881         for (i = 0;i < r_refdef.scene.numentities;i++)
4882         {
4883                 ent = r_refdef.scene.entities[i];
4884
4885                 // skip unseen models
4886                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4887                         continue;
4888
4889                 // skip bsp models
4890                 if (ent->model && ent->model == cl.worldmodel)
4891                 {
4892                         // TODO: use modellight for r_ambient settings on world?
4893                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4894                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4895                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4896                         continue;
4897                 }
4898                 
4899                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4900                 {
4901                         // aleady updated by CSQC
4902                         // TODO: force modellight on BSP models in this case?
4903                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4904                 }
4905                 else
4906                 {
4907                         // fetch the lighting from the worldmodel data
4908                         VectorClear(ent->modellight_ambient);
4909                         VectorClear(ent->modellight_diffuse);
4910                         VectorClear(tempdiffusenormal);
4911                         if (ent->flags & RENDER_LIGHT)
4912                         {
4913                                 vec3_t org;
4914                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4915
4916                                 // complete lightning for lit sprites
4917                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4918                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4919                                 {
4920                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4921                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4922                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4923                                 }
4924                                 else
4925                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4926
4927                                 if(ent->flags & RENDER_EQUALIZE)
4928                                 {
4929                                         // first fix up ambient lighting...
4930                                         if(r_equalize_entities_minambient.value > 0)
4931                                         {
4932                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4933                                                 if(fd > 0)
4934                                                 {
4935                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4936                                                         if(fa < r_equalize_entities_minambient.value * fd)
4937                                                         {
4938                                                                 // solve:
4939                                                                 //   fa'/fd' = minambient
4940                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4941                                                                 //   ...
4942                                                                 //   fa' = fd' * minambient
4943                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4944                                                                 //   ...
4945                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4946                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4947                                                                 //   ...
4948                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4949                                                                 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
4950                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4951                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4952                                                         }
4953                                                 }
4954                                         }
4955
4956                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4957                                         {
4958                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4959                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4960                                                 f = fa + 0.25 * fd;
4961                                                 if(f > 0)
4962                                                 {
4963                                                         // adjust brightness and saturation to target
4964                                                         avg[0] = avg[1] = avg[2] = fa / f;
4965                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4966                                                         avg[0] = avg[1] = avg[2] = fd / f;
4967                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4968                                                 }
4969                                         }
4970                                 }
4971                         }
4972                         else // highly rare
4973                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4974                 }
4975
4976                 // move the light direction into modelspace coordinates for lighting code
4977                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4978                 if(VectorLength2(ent->modellight_lightdir) == 0)
4979                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4980                 VectorNormalize(ent->modellight_lightdir);
4981         }
4982 }
4983
4984 #define MAX_LINEOFSIGHTTRACES 64
4985
4986 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4987 {
4988         int i;
4989         vec3_t boxmins, boxmaxs;
4990         vec3_t start;
4991         vec3_t end;
4992         dp_model_t *model = r_refdef.scene.worldmodel;
4993
4994         if (!model || !model->brush.TraceLineOfSight)
4995                 return true;
4996
4997         // expand the box a little
4998         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4999         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5000         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5001         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5002         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5003         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5004
5005         // return true if eye is inside enlarged box
5006         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5007                 return true;
5008
5009         // try center
5010         VectorCopy(eye, start);
5011         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5012         if (model->brush.TraceLineOfSight(model, start, end))
5013                 return true;
5014
5015         // try various random positions
5016         for (i = 0;i < numsamples;i++)
5017         {
5018                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5019                 if (model->brush.TraceLineOfSight(model, start, end))
5020                         return true;
5021         }
5022
5023         return false;
5024 }
5025
5026
5027 static void R_View_UpdateEntityVisible (void)
5028 {
5029         int i;
5030         int renderimask;
5031         int samples;
5032         entity_render_t *ent;
5033
5034         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5035                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5036                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5037                 :                                                          RENDER_EXTERIORMODEL;
5038         if (!r_drawviewmodel.integer)
5039                 renderimask |= RENDER_VIEWMODEL;
5040         if (!r_drawexteriormodel.integer)
5041                 renderimask |= RENDER_EXTERIORMODEL;
5042         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5043         {
5044                 // worldmodel can check visibility
5045                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5046                 for (i = 0;i < r_refdef.scene.numentities;i++)
5047                 {
5048                         ent = r_refdef.scene.entities[i];
5049                         if (!(ent->flags & renderimask))
5050                         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)))
5051                         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))
5052                                 r_refdef.viewcache.entityvisible[i] = true;
5053                 }
5054         }
5055         else
5056         {
5057                 // no worldmodel or it can't check visibility
5058                 for (i = 0;i < r_refdef.scene.numentities;i++)
5059                 {
5060                         ent = r_refdef.scene.entities[i];
5061                         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));
5062                 }
5063         }
5064         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5065                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5066         {
5067                 for (i = 0;i < r_refdef.scene.numentities;i++)
5068                 {
5069                         if (!r_refdef.viewcache.entityvisible[i])
5070                                 continue;
5071                         ent = r_refdef.scene.entities[i];
5072                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5073                         {
5074                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5075                                 if (samples < 0)
5076                                         continue; // temp entities do pvs only
5077                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5078                                         ent->last_trace_visibility = realtime;
5079                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5080                                         r_refdef.viewcache.entityvisible[i] = 0;
5081                         }
5082                 }
5083         }
5084 }
5085
5086 /// only used if skyrendermasked, and normally returns false
5087 static int R_DrawBrushModelsSky (void)
5088 {
5089         int i, sky;
5090         entity_render_t *ent;
5091
5092         sky = false;
5093         for (i = 0;i < r_refdef.scene.numentities;i++)
5094         {
5095                 if (!r_refdef.viewcache.entityvisible[i])
5096                         continue;
5097                 ent = r_refdef.scene.entities[i];
5098                 if (!ent->model || !ent->model->DrawSky)
5099                         continue;
5100                 ent->model->DrawSky(ent);
5101                 sky = true;
5102         }
5103         return sky;
5104 }
5105
5106 static void R_DrawNoModel(entity_render_t *ent);
5107 static void R_DrawModels(void)
5108 {
5109         int i;
5110         entity_render_t *ent;
5111
5112         for (i = 0;i < r_refdef.scene.numentities;i++)
5113         {
5114                 if (!r_refdef.viewcache.entityvisible[i])
5115                         continue;
5116                 ent = r_refdef.scene.entities[i];
5117                 r_refdef.stats.entities++;
5118                 /*
5119                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5120                 {
5121                         vec3_t f, l, u, o;
5122                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5123                         Con_Printf("R_DrawModels\n");
5124                         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]);
5125                         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);
5126                         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);
5127                 }
5128                 */
5129                 if (ent->model && ent->model->Draw != NULL)
5130                         ent->model->Draw(ent);
5131                 else
5132                         R_DrawNoModel(ent);
5133         }
5134 }
5135
5136 static void R_DrawModelsDepth(void)
5137 {
5138         int i;
5139         entity_render_t *ent;
5140
5141         for (i = 0;i < r_refdef.scene.numentities;i++)
5142         {
5143                 if (!r_refdef.viewcache.entityvisible[i])
5144                         continue;
5145                 ent = r_refdef.scene.entities[i];
5146                 if (ent->model && ent->model->DrawDepth != NULL)
5147                         ent->model->DrawDepth(ent);
5148         }
5149 }
5150
5151 static void R_DrawModelsDebug(void)
5152 {
5153         int i;
5154         entity_render_t *ent;
5155
5156         for (i = 0;i < r_refdef.scene.numentities;i++)
5157         {
5158                 if (!r_refdef.viewcache.entityvisible[i])
5159                         continue;
5160                 ent = r_refdef.scene.entities[i];
5161                 if (ent->model && ent->model->DrawDebug != NULL)
5162                         ent->model->DrawDebug(ent);
5163         }
5164 }
5165
5166 static void R_DrawModelsAddWaterPlanes(void)
5167 {
5168         int i;
5169         entity_render_t *ent;
5170
5171         for (i = 0;i < r_refdef.scene.numentities;i++)
5172         {
5173                 if (!r_refdef.viewcache.entityvisible[i])
5174                         continue;
5175                 ent = r_refdef.scene.entities[i];
5176                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5177                         ent->model->DrawAddWaterPlanes(ent);
5178         }
5179 }
5180
5181 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}};
5182
5183 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5184 {
5185         if (r_hdr_irisadaptation.integer)
5186         {
5187                 vec3_t p;
5188                 vec3_t ambient;
5189                 vec3_t diffuse;
5190                 vec3_t diffusenormal;
5191                 vec3_t forward;
5192                 vec_t brightness = 0.0f;
5193                 vec_t goal;
5194                 vec_t current;
5195                 vec_t d;
5196                 int c;
5197                 VectorCopy(r_refdef.view.forward, forward);
5198                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5199                 {
5200                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5201                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5202                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5203                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5204                         d = DotProduct(forward, diffusenormal);
5205                         brightness += VectorLength(ambient);
5206                         if (d > 0)
5207                                 brightness += d * VectorLength(diffuse);
5208                 }
5209                 brightness *= 1.0f / c;
5210                 brightness += 0.00001f; // make sure it's never zero
5211                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5212                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5213                 current = r_hdr_irisadaptation_value.value;
5214                 if (current < goal)
5215                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5216                 else if (current > goal)
5217                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5218                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5219                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5220         }
5221         else if (r_hdr_irisadaptation_value.value != 1.0f)
5222                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5223 }
5224
5225 static void R_View_SetFrustum(const int *scissor)
5226 {
5227         int i;
5228         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5229         vec3_t forward, left, up, origin, v;
5230
5231         if(scissor)
5232         {
5233                 // flipped x coordinates (because x points left here)
5234                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5235                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5236
5237                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5238                 switch(vid.renderpath)
5239                 {
5240                         case RENDERPATH_D3D9:
5241                         case RENDERPATH_D3D10:
5242                         case RENDERPATH_D3D11:
5243                                 // non-flipped y coordinates
5244                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5245                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5246                                 break;
5247                         case RENDERPATH_SOFT:
5248                         case RENDERPATH_GL11:
5249                         case RENDERPATH_GL13:
5250                         case RENDERPATH_GL20:
5251                         case RENDERPATH_GLES1:
5252                         case RENDERPATH_GLES2:
5253                                 // non-flipped y coordinates
5254                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5255                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5256                                 break;
5257                 }
5258         }
5259
5260         // we can't trust r_refdef.view.forward and friends in reflected scenes
5261         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5262
5263 #if 0
5264         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5265         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5266         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5267         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5268         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5269         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5270         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5271         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5272         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5273         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5274         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5275         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5276 #endif
5277
5278 #if 0
5279         zNear = r_refdef.nearclip;
5280         nudge = 1.0 - 1.0 / (1<<23);
5281         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5282         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5283         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5284         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5285         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5286         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5287         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5288         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5289 #endif
5290
5291
5292
5293 #if 0
5294         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5295         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5296         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5297         r_refdef.view.frustum[0].dist = m[15] - m[12];
5298
5299         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5300         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5301         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5302         r_refdef.view.frustum[1].dist = m[15] + m[12];
5303
5304         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5305         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5306         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5307         r_refdef.view.frustum[2].dist = m[15] - m[13];
5308
5309         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5310         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5311         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5312         r_refdef.view.frustum[3].dist = m[15] + m[13];
5313
5314         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5315         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5316         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5317         r_refdef.view.frustum[4].dist = m[15] - m[14];
5318
5319         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5320         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5321         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5322         r_refdef.view.frustum[5].dist = m[15] + m[14];
5323 #endif
5324
5325         if (r_refdef.view.useperspective)
5326         {
5327                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5328                 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]);
5329                 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]);
5330                 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]);
5331                 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]);
5332
5333                 // then the normals from the corners relative to origin
5334                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5335                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5336                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5337                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5338
5339                 // in a NORMAL view, forward cross left == up
5340                 // in a REFLECTED view, forward cross left == down
5341                 // so our cross products above need to be adjusted for a left handed coordinate system
5342                 CrossProduct(forward, left, v);
5343                 if(DotProduct(v, up) < 0)
5344                 {
5345                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5346                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5347                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5348                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5349                 }
5350
5351                 // Leaving those out was a mistake, those were in the old code, and they
5352                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5353                 // I couldn't reproduce it after adding those normalizations. --blub
5354                 VectorNormalize(r_refdef.view.frustum[0].normal);
5355                 VectorNormalize(r_refdef.view.frustum[1].normal);
5356                 VectorNormalize(r_refdef.view.frustum[2].normal);
5357                 VectorNormalize(r_refdef.view.frustum[3].normal);
5358
5359                 // make the corners absolute
5360                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5361                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5362                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5363                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5364
5365                 // one more normal
5366                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5367
5368                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5369                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5370                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5371                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5372                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5373         }
5374         else
5375         {
5376                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5377                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5378                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5379                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5380                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5381                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5382                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5383                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5384                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5385                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5386         }
5387         r_refdef.view.numfrustumplanes = 5;
5388
5389         if (r_refdef.view.useclipplane)
5390         {
5391                 r_refdef.view.numfrustumplanes = 6;
5392                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5393         }
5394
5395         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5396                 PlaneClassify(r_refdef.view.frustum + i);
5397
5398         // LordHavoc: note to all quake engine coders, Quake had a special case
5399         // for 90 degrees which assumed a square view (wrong), so I removed it,
5400         // Quake2 has it disabled as well.
5401
5402         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5403         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5404         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5405         //PlaneClassify(&frustum[0]);
5406
5407         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5408         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5409         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5410         //PlaneClassify(&frustum[1]);
5411
5412         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5413         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5414         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5415         //PlaneClassify(&frustum[2]);
5416
5417         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5418         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5419         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5420         //PlaneClassify(&frustum[3]);
5421
5422         // nearclip plane
5423         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5424         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5425         //PlaneClassify(&frustum[4]);
5426 }
5427
5428 static void R_View_UpdateWithScissor(const int *myscissor)
5429 {
5430         R_Main_ResizeViewCache();
5431         R_View_SetFrustum(myscissor);
5432         R_View_WorldVisibility(r_refdef.view.useclipplane);
5433         R_View_UpdateEntityVisible();
5434         R_View_UpdateEntityLighting();
5435 }
5436
5437 static void R_View_Update(void)
5438 {
5439         R_Main_ResizeViewCache();
5440         R_View_SetFrustum(NULL);
5441         R_View_WorldVisibility(r_refdef.view.useclipplane);
5442         R_View_UpdateEntityVisible();
5443         R_View_UpdateEntityLighting();
5444 }
5445
5446 float viewscalefpsadjusted = 1.0f;
5447
5448 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5449 {
5450         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5451         scale = bound(0.03125f, scale, 1.0f);
5452         *outwidth = (int)ceil(width * scale);
5453         *outheight = (int)ceil(height * scale);
5454 }
5455
5456 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5457 {
5458         const float *customclipplane = NULL;
5459         float plane[4];
5460         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5461         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5462         {
5463                 // LordHavoc: couldn't figure out how to make this approach the
5464                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5465                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5466                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5467                         dist = r_refdef.view.clipplane.dist;
5468                 plane[0] = r_refdef.view.clipplane.normal[0];
5469                 plane[1] = r_refdef.view.clipplane.normal[1];
5470                 plane[2] = r_refdef.view.clipplane.normal[2];
5471                 plane[3] = -dist;
5472                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5473         }
5474
5475         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5476         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5477
5478         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5479         if (!r_refdef.view.useperspective)
5480                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5481         else if (vid.stencil && r_useinfinitefarclip.integer)
5482                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5483         else
5484                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5485         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5486         R_SetViewport(&r_refdef.view.viewport);
5487         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5488         {
5489                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5490                 float screenplane[4];
5491                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5492                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5493                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5494                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5495                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5496         }
5497 }
5498
5499 void R_EntityMatrix(const matrix4x4_t *matrix)
5500 {
5501         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5502         {
5503                 gl_modelmatrixchanged = false;
5504                 gl_modelmatrix = *matrix;
5505                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5506                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5507                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5508                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5509                 CHECKGLERROR
5510                 switch(vid.renderpath)
5511                 {
5512                 case RENDERPATH_D3D9:
5513 #ifdef SUPPORTD3D
5514                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5515                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5516 #endif
5517                         break;
5518                 case RENDERPATH_D3D10:
5519                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5520                         break;
5521                 case RENDERPATH_D3D11:
5522                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5523                         break;
5524                 case RENDERPATH_GL11:
5525                 case RENDERPATH_GL13:
5526                 case RENDERPATH_GLES1:
5527                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5528                         break;
5529                 case RENDERPATH_SOFT:
5530                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5531                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5532                         break;
5533                 case RENDERPATH_GL20:
5534                 case RENDERPATH_GLES2:
5535                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5536                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5537                         break;
5538                 }
5539         }
5540 }
5541
5542 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5543 {
5544         r_viewport_t viewport;
5545
5546         CHECKGLERROR
5547
5548         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5549         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, x2, y2, -10, 100, NULL);
5550         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5551         R_SetViewport(&viewport);
5552         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5553         GL_Color(1, 1, 1, 1);
5554         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5555         GL_BlendFunc(GL_ONE, GL_ZERO);
5556         GL_ScissorTest(false);
5557         GL_DepthMask(false);
5558         GL_DepthRange(0, 1);
5559         GL_DepthTest(false);
5560         GL_DepthFunc(GL_LEQUAL);
5561         R_EntityMatrix(&identitymatrix);
5562         R_Mesh_ResetTextureState();
5563         GL_PolygonOffset(0, 0);
5564         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5565         switch(vid.renderpath)
5566         {
5567         case RENDERPATH_GL11:
5568         case RENDERPATH_GL13:
5569         case RENDERPATH_GL20:
5570         case RENDERPATH_GLES1:
5571         case RENDERPATH_GLES2:
5572                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5573                 break;
5574         case RENDERPATH_D3D9:
5575         case RENDERPATH_D3D10:
5576         case RENDERPATH_D3D11:
5577         case RENDERPATH_SOFT:
5578                 break;
5579         }
5580         GL_CullFace(GL_NONE);
5581
5582         CHECKGLERROR
5583 }
5584
5585 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5586 {
5587         DrawQ_Finish();
5588
5589         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5590 }
5591
5592 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5593 {
5594         DrawQ_Finish();
5595
5596         R_SetupView(true, fbo, depthtexture, colortexture);
5597         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5598         GL_Color(1, 1, 1, 1);
5599         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5600         GL_BlendFunc(GL_ONE, GL_ZERO);
5601         GL_ScissorTest(true);
5602         GL_DepthMask(true);
5603         GL_DepthRange(0, 1);
5604         GL_DepthTest(true);
5605         GL_DepthFunc(GL_LEQUAL);
5606         R_EntityMatrix(&identitymatrix);
5607         R_Mesh_ResetTextureState();
5608         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5609         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5610         switch(vid.renderpath)
5611         {
5612         case RENDERPATH_GL11:
5613         case RENDERPATH_GL13:
5614         case RENDERPATH_GL20:
5615         case RENDERPATH_GLES1:
5616         case RENDERPATH_GLES2:
5617                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5618                 break;
5619         case RENDERPATH_D3D9:
5620         case RENDERPATH_D3D10:
5621         case RENDERPATH_D3D11:
5622         case RENDERPATH_SOFT:
5623                 break;
5624         }
5625         GL_CullFace(r_refdef.view.cullface_back);
5626 }
5627
5628 /*
5629 ================
5630 R_RenderView_UpdateViewVectors
5631 ================
5632 */
5633 void R_RenderView_UpdateViewVectors(void)
5634 {
5635         // break apart the view matrix into vectors for various purposes
5636         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5637         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5638         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5639         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5640         // make an inverted copy of the view matrix for tracking sprites
5641         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5642 }
5643
5644 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5645 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5646
5647 static void R_Water_StartFrame(void)
5648 {
5649         int i;
5650         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5651         r_waterstate_waterplane_t *p;
5652         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5653
5654         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5655                 return;
5656
5657         switch(vid.renderpath)
5658         {
5659         case RENDERPATH_GL20:
5660         case RENDERPATH_D3D9:
5661         case RENDERPATH_D3D10:
5662         case RENDERPATH_D3D11:
5663         case RENDERPATH_SOFT:
5664         case RENDERPATH_GLES2:
5665                 break;
5666         case RENDERPATH_GL11:
5667         case RENDERPATH_GL13:
5668         case RENDERPATH_GLES1:
5669                 return;
5670         }
5671
5672         // set waterwidth and waterheight to the water resolution that will be
5673         // used (often less than the screen resolution for faster rendering)
5674         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5675
5676         // calculate desired texture sizes
5677         // can't use water if the card does not support the texture size
5678         if (!r_water.integer || r_showsurfaces.integer)
5679                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5680         else if (vid.support.arb_texture_non_power_of_two)
5681         {
5682                 texturewidth = waterwidth;
5683                 textureheight = waterheight;
5684                 camerawidth = waterwidth;
5685                 cameraheight = waterheight;
5686         }
5687         else
5688         {
5689                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5690                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5691                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5692                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5693         }
5694
5695         // allocate textures as needed
5696         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5697         {
5698                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5699                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5700                 {
5701                         if (p->texture_refraction)
5702                                 R_FreeTexture(p->texture_refraction);
5703                         p->texture_refraction = NULL;
5704                         if (p->fbo_refraction)
5705                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5706                         p->fbo_refraction = 0;
5707                         if (p->texture_reflection)
5708                                 R_FreeTexture(p->texture_reflection);
5709                         p->texture_reflection = NULL;
5710                         if (p->fbo_reflection)
5711                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5712                         p->fbo_reflection = 0;
5713                         if (p->texture_camera)
5714                                 R_FreeTexture(p->texture_camera);
5715                         p->texture_camera = NULL;
5716                         if (p->fbo_camera)
5717                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5718                         p->fbo_camera = 0;
5719                 }
5720                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5721                 r_fb.water.texturewidth = texturewidth;
5722                 r_fb.water.textureheight = textureheight;
5723                 r_fb.water.camerawidth = camerawidth;
5724                 r_fb.water.cameraheight = cameraheight;
5725         }
5726
5727         if (r_fb.water.texturewidth)
5728         {
5729                 int scaledwidth, scaledheight;
5730
5731                 r_fb.water.enabled = true;
5732
5733                 // water resolution is usually reduced
5734                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5735                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5736                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5737
5738                 // set up variables that will be used in shader setup
5739                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5740                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5741                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5742                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5743         }
5744
5745         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5746         r_fb.water.numwaterplanes = 0;
5747 }
5748
5749 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5750 {
5751         int planeindex, bestplaneindex, vertexindex;
5752         vec3_t mins, maxs, normal, center, v, n;
5753         vec_t planescore, bestplanescore;
5754         mplane_t plane;
5755         r_waterstate_waterplane_t *p;
5756         texture_t *t = R_GetCurrentTexture(surface->texture);
5757
5758         rsurface.texture = t;
5759         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5760         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5761         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5762                 return;
5763         // average the vertex normals, find the surface bounds (after deformvertexes)
5764         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5765         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5766         VectorCopy(n, normal);
5767         VectorCopy(v, mins);
5768         VectorCopy(v, maxs);
5769         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5770         {
5771                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5772                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5773                 VectorAdd(normal, n, normal);
5774                 mins[0] = min(mins[0], v[0]);
5775                 mins[1] = min(mins[1], v[1]);
5776                 mins[2] = min(mins[2], v[2]);
5777                 maxs[0] = max(maxs[0], v[0]);
5778                 maxs[1] = max(maxs[1], v[1]);
5779                 maxs[2] = max(maxs[2], v[2]);
5780         }
5781         VectorNormalize(normal);
5782         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5783
5784         VectorCopy(normal, plane.normal);
5785         VectorNormalize(plane.normal);
5786         plane.dist = DotProduct(center, plane.normal);
5787         PlaneClassify(&plane);
5788         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5789         {
5790                 // skip backfaces (except if nocullface is set)
5791 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5792 //                      return;
5793                 VectorNegate(plane.normal, plane.normal);
5794                 plane.dist *= -1;
5795                 PlaneClassify(&plane);
5796         }
5797
5798
5799         // find a matching plane if there is one
5800         bestplaneindex = -1;
5801         bestplanescore = 1048576.0f;
5802         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5803         {
5804                 if(p->camera_entity == t->camera_entity)
5805                 {
5806                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5807                         if (bestplaneindex < 0 || bestplanescore > planescore)
5808                         {
5809                                 bestplaneindex = planeindex;
5810                                 bestplanescore = planescore;
5811                         }
5812                 }
5813         }
5814         planeindex = bestplaneindex;
5815         p = r_fb.water.waterplanes + planeindex;
5816
5817         // if this surface does not fit any known plane rendered this frame, add one
5818         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5819         {
5820                 // store the new plane
5821                 planeindex = r_fb.water.numwaterplanes++;
5822                 p = r_fb.water.waterplanes + planeindex;
5823                 p->plane = plane;
5824                 // clear materialflags and pvs
5825                 p->materialflags = 0;
5826                 p->pvsvalid = false;
5827                 p->camera_entity = t->camera_entity;
5828                 VectorCopy(mins, p->mins);
5829                 VectorCopy(maxs, p->maxs);
5830         }
5831         else
5832         {
5833                 // merge mins/maxs when we're adding this surface to the plane
5834                 p->mins[0] = min(p->mins[0], mins[0]);
5835                 p->mins[1] = min(p->mins[1], mins[1]);
5836                 p->mins[2] = min(p->mins[2], mins[2]);
5837                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5838                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5839                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5840         }
5841         // merge this surface's materialflags into the waterplane
5842         p->materialflags |= t->currentmaterialflags;
5843         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5844         {
5845                 // merge this surface's PVS into the waterplane
5846                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5847                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5848                 {
5849                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5850                         p->pvsvalid = true;
5851                 }
5852         }
5853 }
5854
5855 extern cvar_t r_drawparticles;
5856 extern cvar_t r_drawdecals;
5857
5858 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5859 {
5860         int myscissor[4];
5861         r_refdef_view_t originalview;
5862         r_refdef_view_t myview;
5863         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;
5864         r_waterstate_waterplane_t *p;
5865         vec3_t visorigin;
5866         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5867         char vabuf[1024];
5868
5869         originalview = r_refdef.view;
5870
5871         // lowquality hack, temporarily shut down some cvars and restore afterwards
5872         qualityreduction = r_water_lowquality.integer;
5873         if (qualityreduction > 0)
5874         {
5875                 if (qualityreduction >= 1)
5876                 {
5877                         old_r_shadows = r_shadows.integer;
5878                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5879                         old_r_dlight = r_shadow_realtime_dlight.integer;
5880                         Cvar_SetValueQuick(&r_shadows, 0);
5881                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5882                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5883                 }
5884                 if (qualityreduction >= 2)
5885                 {
5886                         old_r_dynamic = r_dynamic.integer;
5887                         old_r_particles = r_drawparticles.integer;
5888                         old_r_decals = r_drawdecals.integer;
5889                         Cvar_SetValueQuick(&r_dynamic, 0);
5890                         Cvar_SetValueQuick(&r_drawparticles, 0);
5891                         Cvar_SetValueQuick(&r_drawdecals, 0);
5892                 }
5893         }
5894
5895         // make sure enough textures are allocated
5896         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5897         {
5898                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5899                 {
5900                         if (!p->texture_refraction)
5901                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5902                         if (!p->texture_refraction)
5903                                 goto error;
5904                         if (usewaterfbo)
5905                         {
5906                                 if (r_fb.water.depthtexture == NULL)
5907                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5908                                 if (p->fbo_refraction == 0)
5909                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5910                         }
5911                 }
5912                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5913                 {
5914                         if (!p->texture_camera)
5915                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5916                         if (!p->texture_camera)
5917                                 goto error;
5918                         if (usewaterfbo)
5919                         {
5920                                 if (r_fb.water.depthtexture == NULL)
5921                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5922                                 if (p->fbo_camera == 0)
5923                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5924                         }
5925                 }
5926
5927                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5928                 {
5929                         if (!p->texture_reflection)
5930                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5931                         if (!p->texture_reflection)
5932                                 goto error;
5933                         if (usewaterfbo)
5934                         {
5935                                 if (r_fb.water.depthtexture == NULL)
5936                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5937                                 if (p->fbo_reflection == 0)
5938                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5939                         }
5940                 }
5941         }
5942
5943         // render views
5944         r_refdef.view = originalview;
5945         r_refdef.view.showdebug = false;
5946         r_refdef.view.width = r_fb.water.waterwidth;
5947         r_refdef.view.height = r_fb.water.waterheight;
5948         r_refdef.view.useclipplane = true;
5949         myview = r_refdef.view;
5950         r_fb.water.renderingscene = true;
5951         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5952         {
5953                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5954                 {
5955                         r_refdef.view = myview;
5956                         if(r_water_scissormode.integer)
5957                         {
5958                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5959                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5960                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5961                         }
5962
5963                         // render reflected scene and copy into texture
5964                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5965                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5966                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5967                         r_refdef.view.clipplane = p->plane;
5968                         // reverse the cullface settings for this render
5969                         r_refdef.view.cullface_front = GL_FRONT;
5970                         r_refdef.view.cullface_back = GL_BACK;
5971                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5972                         {
5973                                 r_refdef.view.usecustompvs = true;
5974                                 if (p->pvsvalid)
5975                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5976                                 else
5977                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5978                         }
5979
5980                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5981                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5982                         R_ClearScreen(r_refdef.fogenabled);
5983                         if(r_water_scissormode.integer & 2)
5984                                 R_View_UpdateWithScissor(myscissor);
5985                         else
5986                                 R_View_Update();
5987                         R_AnimCache_CacheVisibleEntities();
5988                         if(r_water_scissormode.integer & 1)
5989                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5990                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5991
5992                         if (!p->fbo_reflection)
5993                                 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);
5994                         r_fb.water.hideplayer = false;
5995                 }
5996
5997                 // render the normal view scene and copy into texture
5998                 // (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)
5999                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6000                 {
6001                         r_refdef.view = myview;
6002                         if(r_water_scissormode.integer)
6003                         {
6004                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6005                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6006                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6007                         }
6008
6009                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6010
6011                         r_refdef.view.clipplane = p->plane;
6012                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6013                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6014
6015                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6016                         {
6017                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6018                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6019                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6020                                 R_RenderView_UpdateViewVectors();
6021                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6022                                 {
6023                                         r_refdef.view.usecustompvs = true;
6024                                         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);
6025                                 }
6026                         }
6027
6028                         PlaneClassify(&r_refdef.view.clipplane);
6029
6030                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6031                         R_ClearScreen(r_refdef.fogenabled);
6032                         if(r_water_scissormode.integer & 2)
6033                                 R_View_UpdateWithScissor(myscissor);
6034                         else
6035                                 R_View_Update();
6036                         R_AnimCache_CacheVisibleEntities();
6037                         if(r_water_scissormode.integer & 1)
6038                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6039                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6040
6041                         if (!p->fbo_refraction)
6042                                 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);
6043                         r_fb.water.hideplayer = false;
6044                 }
6045                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6046                 {
6047                         r_refdef.view = myview;
6048
6049                         r_refdef.view.clipplane = p->plane;
6050                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6051                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6052
6053                         r_refdef.view.width = r_fb.water.camerawidth;
6054                         r_refdef.view.height = r_fb.water.cameraheight;
6055                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6056                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6057                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6058                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6059
6060                         if(p->camera_entity)
6061                         {
6062                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6063                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6064                         }
6065
6066                         // note: all of the view is used for displaying... so
6067                         // there is no use in scissoring
6068
6069                         // reverse the cullface settings for this render
6070                         r_refdef.view.cullface_front = GL_FRONT;
6071                         r_refdef.view.cullface_back = GL_BACK;
6072                         // also reverse the view matrix
6073                         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
6074                         R_RenderView_UpdateViewVectors();
6075                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6076                         {
6077                                 r_refdef.view.usecustompvs = true;
6078                                 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);
6079                         }
6080                         
6081                         // camera needs no clipplane
6082                         r_refdef.view.useclipplane = false;
6083
6084                         PlaneClassify(&r_refdef.view.clipplane);
6085
6086                         r_fb.water.hideplayer = false;
6087
6088                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6089                         R_ClearScreen(r_refdef.fogenabled);
6090                         R_View_Update();
6091                         R_AnimCache_CacheVisibleEntities();
6092                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6093
6094                         if (!p->fbo_camera)
6095                                 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);
6096                         r_fb.water.hideplayer = false;
6097                 }
6098
6099         }
6100         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6101         r_fb.water.renderingscene = false;
6102         r_refdef.view = originalview;
6103         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6104         if (!r_fb.water.depthtexture)
6105                 R_ClearScreen(r_refdef.fogenabled);
6106         R_View_Update();
6107         R_AnimCache_CacheVisibleEntities();
6108         goto finish;
6109 error:
6110         r_refdef.view = originalview;
6111         r_fb.water.renderingscene = false;
6112         Cvar_SetValueQuick(&r_water, 0);
6113         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6114 finish:
6115         // lowquality hack, restore cvars
6116         if (qualityreduction > 0)
6117         {
6118                 if (qualityreduction >= 1)
6119                 {
6120                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6121                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6122                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6123                 }
6124                 if (qualityreduction >= 2)
6125                 {
6126                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6127                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6128                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6129                 }
6130         }
6131 }
6132
6133 static void R_Bloom_StartFrame(void)
6134 {
6135         int i;
6136         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6137         int viewwidth, viewheight;
6138         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6139         textype_t textype = TEXTYPE_COLORBUFFER;
6140
6141         switch (vid.renderpath)
6142         {
6143         case RENDERPATH_GL20:
6144                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6145                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6146                 {
6147                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6148                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6149                 }
6150                 break;
6151         case RENDERPATH_GL11:
6152         case RENDERPATH_GL13:
6153         case RENDERPATH_GLES1:
6154         case RENDERPATH_GLES2:
6155         case RENDERPATH_D3D9:
6156         case RENDERPATH_D3D10:
6157         case RENDERPATH_D3D11:
6158                 r_fb.usedepthtextures = false;
6159                 break;
6160         case RENDERPATH_SOFT:
6161                 r_fb.usedepthtextures = true;
6162                 break;
6163         }
6164
6165         if (r_viewscale_fpsscaling.integer)
6166         {
6167                 double actualframetime;
6168                 double targetframetime;
6169                 double adjust;
6170                 actualframetime = r_refdef.lastdrawscreentime;
6171                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6172                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6173                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6174                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6175                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6176                 viewscalefpsadjusted += adjust;
6177                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6178         }
6179         else
6180                 viewscalefpsadjusted = 1.0f;
6181
6182         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6183
6184         switch(vid.renderpath)
6185         {
6186         case RENDERPATH_GL20:
6187         case RENDERPATH_D3D9:
6188         case RENDERPATH_D3D10:
6189         case RENDERPATH_D3D11:
6190         case RENDERPATH_SOFT:
6191         case RENDERPATH_GLES2:
6192                 break;
6193         case RENDERPATH_GL11:
6194         case RENDERPATH_GL13:
6195         case RENDERPATH_GLES1:
6196                 return;
6197         }
6198
6199         // set bloomwidth and bloomheight to the bloom resolution that will be
6200         // used (often less than the screen resolution for faster rendering)
6201         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6202         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6203         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6204         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6205         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6206
6207         // calculate desired texture sizes
6208         if (vid.support.arb_texture_non_power_of_two)
6209         {
6210                 screentexturewidth = vid.width;
6211                 screentextureheight = vid.height;
6212                 bloomtexturewidth = r_fb.bloomwidth;
6213                 bloomtextureheight = r_fb.bloomheight;
6214         }
6215         else
6216         {
6217                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6218                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6219                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6220                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6221         }
6222
6223         if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6224         {
6225                 Cvar_SetValueQuick(&r_bloom, 0);
6226                 Cvar_SetValueQuick(&r_motionblur, 0);
6227                 Cvar_SetValueQuick(&r_damageblur, 0);
6228         }
6229
6230         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6231          && !r_bloom.integer
6232          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6233          && !useviewfbo
6234          && r_viewscale.value == 1.0f
6235          && !r_viewscale_fpsscaling.integer)
6236                 screentexturewidth = screentextureheight = 0;
6237         if (!r_bloom.integer)
6238                 bloomtexturewidth = bloomtextureheight = 0;
6239
6240         // allocate textures as needed
6241         if (r_fb.screentexturewidth != screentexturewidth
6242          || r_fb.screentextureheight != screentextureheight
6243          || r_fb.bloomtexturewidth != bloomtexturewidth
6244          || r_fb.bloomtextureheight != bloomtextureheight
6245          || r_fb.textype != textype
6246          || useviewfbo != (r_fb.fbo != 0))
6247         {
6248                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6249                 {
6250                         if (r_fb.bloomtexture[i])
6251                                 R_FreeTexture(r_fb.bloomtexture[i]);
6252                         r_fb.bloomtexture[i] = NULL;
6253
6254                         if (r_fb.bloomfbo[i])
6255                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6256                         r_fb.bloomfbo[i] = 0;
6257                 }
6258
6259                 if (r_fb.fbo)
6260                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6261                 r_fb.fbo = 0;
6262
6263                 if (r_fb.colortexture)
6264                         R_FreeTexture(r_fb.colortexture);
6265                 r_fb.colortexture = NULL;
6266
6267                 if (r_fb.depthtexture)
6268                         R_FreeTexture(r_fb.depthtexture);
6269                 r_fb.depthtexture = NULL;
6270
6271                 if (r_fb.ghosttexture)
6272                         R_FreeTexture(r_fb.ghosttexture);
6273                 r_fb.ghosttexture = NULL;
6274
6275                 r_fb.screentexturewidth = screentexturewidth;
6276                 r_fb.screentextureheight = screentextureheight;
6277                 r_fb.bloomtexturewidth = bloomtexturewidth;
6278                 r_fb.bloomtextureheight = bloomtextureheight;
6279                 r_fb.textype = textype;
6280
6281                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6282                 {
6283                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6284                                 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6285                         r_fb.ghosttexture_valid = false;
6286                         r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6287                         if (useviewfbo)
6288                         {
6289                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6290                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6291                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6292                         }
6293                 }
6294
6295                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6296                 {
6297                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6298                         {
6299                                 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6300                                 if (useviewfbo)
6301                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6302                         }
6303                 }
6304         }
6305
6306         // bloom texture is a different resolution
6307         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6308         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6309         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6310         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6311         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6312
6313         // set up a texcoord array for the full resolution screen image
6314         // (we have to keep this around to copy back during final render)
6315         r_fb.screentexcoord2f[0] = 0;
6316         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6317         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6318         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6319         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6320         r_fb.screentexcoord2f[5] = 0;
6321         r_fb.screentexcoord2f[6] = 0;
6322         r_fb.screentexcoord2f[7] = 0;
6323
6324         if(r_fb.fbo) 
6325         {
6326                 for (i = 1;i < 8;i += 2)
6327                 {
6328                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6329                 }
6330         }
6331
6332         // set up a texcoord array for the reduced resolution bloom image
6333         // (which will be additive blended over the screen image)
6334         r_fb.bloomtexcoord2f[0] = 0;
6335         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6336         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6337         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6338         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6339         r_fb.bloomtexcoord2f[5] = 0;
6340         r_fb.bloomtexcoord2f[6] = 0;
6341         r_fb.bloomtexcoord2f[7] = 0;
6342
6343         switch(vid.renderpath)
6344         {
6345         case RENDERPATH_GL11:
6346         case RENDERPATH_GL13:
6347         case RENDERPATH_GL20:
6348         case RENDERPATH_SOFT:
6349         case RENDERPATH_GLES1:
6350         case RENDERPATH_GLES2:
6351                 break;
6352         case RENDERPATH_D3D9:
6353         case RENDERPATH_D3D10:
6354         case RENDERPATH_D3D11:
6355                 for (i = 0;i < 4;i++)
6356                 {
6357                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6358                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6359                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6360                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6361                 }
6362                 break;
6363         }
6364
6365         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6366
6367         if (r_fb.fbo)
6368                 r_refdef.view.clear = true;
6369 }
6370
6371 static void R_Bloom_MakeTexture(void)
6372 {
6373         int x, range, dir;
6374         float xoffset, yoffset, r, brighten;
6375         rtexture_t *intex;
6376         float colorscale = r_bloom_colorscale.value;
6377
6378         r_refdef.stats.bloom++;
6379     
6380 #if 0
6381     // this copy is unnecessary since it happens in R_BlendView already
6382         if (!r_fb.fbo)
6383         {
6384                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6385                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6386         }
6387 #endif
6388
6389         // scale down screen texture to the bloom texture size
6390         CHECKGLERROR
6391         r_fb.bloomindex = 0;
6392         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6393         R_SetViewport(&r_fb.bloomviewport);
6394         GL_DepthTest(false);
6395         GL_BlendFunc(GL_ONE, GL_ZERO);
6396         GL_Color(colorscale, colorscale, colorscale, 1);
6397         // 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...
6398         switch(vid.renderpath)
6399         {
6400         case RENDERPATH_GL11:
6401         case RENDERPATH_GL13:
6402         case RENDERPATH_GL20:
6403         case RENDERPATH_GLES1:
6404         case RENDERPATH_GLES2:
6405         case RENDERPATH_SOFT:
6406                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6407                 break;
6408         case RENDERPATH_D3D9:
6409         case RENDERPATH_D3D10:
6410         case RENDERPATH_D3D11:
6411                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6412                 break;
6413         }
6414         // TODO: do boxfilter scale-down in shader?
6415         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6416         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6417         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6418
6419         // we now have a properly scaled bloom image
6420         if (!r_fb.bloomfbo[r_fb.bloomindex])
6421         {
6422                 // copy it into the bloom texture
6423                 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6424                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6425         }
6426
6427         // multiply bloom image by itself as many times as desired
6428         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6429         {
6430                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6431                 r_fb.bloomindex ^= 1;
6432                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6433                 x *= 2;
6434                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6435                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6436                 {
6437                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6438                         GL_Color(r,r,r,1); // apply fix factor
6439                 }
6440                 else
6441                 {
6442                         if(x <= 2)
6443                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6444                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6445                         GL_Color(1,1,1,1); // no fix factor supported here
6446                 }
6447                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6448                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6449                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6450                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6451
6452                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6453                 {
6454                         // copy the darkened image to a texture
6455                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6456                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6457                 }
6458         }
6459
6460         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6461         brighten = r_bloom_brighten.value;
6462         brighten = sqrt(brighten);
6463         if(range >= 1)
6464                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6465
6466         for (dir = 0;dir < 2;dir++)
6467         {
6468                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6469                 r_fb.bloomindex ^= 1;
6470                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6471                 // blend on at multiple vertical offsets to achieve a vertical blur
6472                 // TODO: do offset blends using GLSL
6473                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6474                 GL_BlendFunc(GL_ONE, GL_ZERO);
6475                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6476                 for (x = -range;x <= range;x++)
6477                 {
6478                         if (!dir){xoffset = 0;yoffset = x;}
6479                         else {xoffset = x;yoffset = 0;}
6480                         xoffset /= (float)r_fb.bloomtexturewidth;
6481                         yoffset /= (float)r_fb.bloomtextureheight;
6482                         // compute a texcoord array with the specified x and y offset
6483                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6484                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6485                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6486                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6487                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6488                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6489                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6490                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6491                         // this r value looks like a 'dot' particle, fading sharply to
6492                         // black at the edges
6493                         // (probably not realistic but looks good enough)
6494                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6495                         //r = brighten/(range*2+1);
6496                         r = brighten / (range * 2 + 1);
6497                         if(range >= 1)
6498                                 r *= (1 - x*x/(float)(range*range));
6499                         GL_Color(r, r, r, 1);
6500                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6501                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6502                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6503                         GL_BlendFunc(GL_ONE, GL_ONE);
6504                 }
6505
6506                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6507                 {
6508                         // copy the vertically or horizontally blurred bloom view to a texture
6509                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6510                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6511                 }
6512         }
6513 }
6514
6515 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6516 {
6517         unsigned int permutation;
6518         float uservecs[4][4];
6519
6520         R_EntityMatrix(&identitymatrix);
6521
6522         switch (vid.renderpath)
6523         {
6524         case RENDERPATH_GL20:
6525         case RENDERPATH_D3D9:
6526         case RENDERPATH_D3D10:
6527         case RENDERPATH_D3D11:
6528         case RENDERPATH_SOFT:
6529         case RENDERPATH_GLES2:
6530                 permutation =
6531                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6532                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6533                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6534                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6535                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6536
6537                 if (r_fb.colortexture)
6538                 {
6539                         if (!r_fb.fbo)
6540                         {
6541                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6542                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6543                         }
6544
6545                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6546                         {
6547                                 // declare variables
6548                                 float blur_factor, blur_mouseaccel, blur_velocity;
6549                                 static float blur_average; 
6550                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6551
6552                                 // set a goal for the factoring
6553                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6554                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6555                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6556                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6557                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6558                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6559
6560                                 // from the goal, pick an averaged value between goal and last value
6561                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6562                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6563
6564                                 // enforce minimum amount of blur 
6565                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6566
6567                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6568
6569                                 // calculate values into a standard alpha
6570                                 cl.motionbluralpha = 1 - exp(-
6571                                                 (
6572                                                  (r_motionblur.value * blur_factor / 80)
6573                                                  +
6574                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6575                                                 )
6576                                                 /
6577                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6578                                           );
6579
6580                                 // randomization for the blur value to combat persistent ghosting
6581                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6582                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6583
6584                                 // apply the blur
6585                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6586                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6587                                 {
6588                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6589                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6590                                         switch(vid.renderpath)
6591                                         {
6592                                         case RENDERPATH_GL11:
6593                                         case RENDERPATH_GL13:
6594                                         case RENDERPATH_GL20:
6595                                         case RENDERPATH_GLES1:
6596                                         case RENDERPATH_GLES2:
6597                                         case RENDERPATH_SOFT:
6598                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6599                                                 break;
6600                                         case RENDERPATH_D3D9:
6601                                         case RENDERPATH_D3D10:
6602                                         case RENDERPATH_D3D11:
6603                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6604                                                 break;
6605                                         }
6606                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6607                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6608                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6609                                 }
6610
6611                                 // updates old view angles for next pass
6612                                 VectorCopy(cl.viewangles, blur_oldangles);
6613
6614                                 // copy view into the ghost texture
6615                                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6616                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6617                                 r_fb.ghosttexture_valid = true;
6618                         }
6619                 }
6620                 else
6621                 {
6622                         // no r_fb.colortexture means we're rendering to the real fb
6623                         // we may still have to do view tint...
6624                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6625                         {
6626                                 // apply a color tint to the whole view
6627                                 R_ResetViewRendering2D(0, NULL, NULL);
6628                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6629                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6630                                 R_SetupShader_Generic_NoTexture(false, true);
6631                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6632                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6633                         }
6634                         break; // no screen processing, no bloom, skip it
6635                 }
6636
6637                 if (r_fb.bloomtexture[0])
6638                 {
6639                         // make the bloom texture
6640                         R_Bloom_MakeTexture();
6641                 }
6642
6643 #if _MSC_VER >= 1400
6644 #define sscanf sscanf_s
6645 #endif
6646                 memset(uservecs, 0, sizeof(uservecs));
6647                 if (r_glsl_postprocess_uservec1_enable.integer)
6648                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6649                 if (r_glsl_postprocess_uservec2_enable.integer)
6650                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6651                 if (r_glsl_postprocess_uservec3_enable.integer)
6652                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6653                 if (r_glsl_postprocess_uservec4_enable.integer)
6654                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6655
6656                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6657                 GL_Color(1, 1, 1, 1);
6658                 GL_BlendFunc(GL_ONE, GL_ZERO);
6659
6660                 switch(vid.renderpath)
6661                 {
6662                 case RENDERPATH_GL20:
6663                 case RENDERPATH_GLES2:
6664                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6665                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6666                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6667                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6668                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6669                         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]);
6670                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6671                         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]);
6672                         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]);
6673                         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]);
6674                         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]);
6675                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6676                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6677                         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);
6678                         break;
6679                 case RENDERPATH_D3D9:
6680 #ifdef SUPPORTD3D
6681                         // 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...
6682                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6683                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6684                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6685                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6686                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6687                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6688                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6689                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6690                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6691                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6692                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6693                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6694                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6695                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6696 #endif
6697                         break;
6698                 case RENDERPATH_D3D10:
6699                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6700                         break;
6701                 case RENDERPATH_D3D11:
6702                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6703                         break;
6704                 case RENDERPATH_SOFT:
6705                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6706                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6707                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6708                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6709                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6710                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6711                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6712                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6713                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6714                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6715                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6716                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6717                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6718                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6719                         break;
6720                 default:
6721                         break;
6722                 }
6723                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6724                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6725                 break;
6726         case RENDERPATH_GL11:
6727         case RENDERPATH_GL13:
6728         case RENDERPATH_GLES1:
6729                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6730                 {
6731                         // apply a color tint to the whole view
6732                         R_ResetViewRendering2D(0, NULL, NULL);
6733                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6734                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6735                         R_SetupShader_Generic_NoTexture(false, true);
6736                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6737                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6738                 }
6739                 break;
6740         }
6741 }
6742
6743 matrix4x4_t r_waterscrollmatrix;
6744
6745 void R_UpdateFog(void)
6746 {
6747         // Nehahra fog
6748         if (gamemode == GAME_NEHAHRA)
6749         {
6750                 if (gl_fogenable.integer)
6751                 {
6752                         r_refdef.oldgl_fogenable = true;
6753                         r_refdef.fog_density = gl_fogdensity.value;
6754                         r_refdef.fog_red = gl_fogred.value;
6755                         r_refdef.fog_green = gl_foggreen.value;
6756                         r_refdef.fog_blue = gl_fogblue.value;
6757                         r_refdef.fog_alpha = 1;
6758                         r_refdef.fog_start = 0;
6759                         r_refdef.fog_end = gl_skyclip.value;
6760                         r_refdef.fog_height = 1<<30;
6761                         r_refdef.fog_fadedepth = 128;
6762                 }
6763                 else if (r_refdef.oldgl_fogenable)
6764                 {
6765                         r_refdef.oldgl_fogenable = false;
6766                         r_refdef.fog_density = 0;
6767                         r_refdef.fog_red = 0;
6768                         r_refdef.fog_green = 0;
6769                         r_refdef.fog_blue = 0;
6770                         r_refdef.fog_alpha = 0;
6771                         r_refdef.fog_start = 0;
6772                         r_refdef.fog_end = 0;
6773                         r_refdef.fog_height = 1<<30;
6774                         r_refdef.fog_fadedepth = 128;
6775                 }
6776         }
6777
6778         // fog parms
6779         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6780         r_refdef.fog_start = max(0, r_refdef.fog_start);
6781         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6782
6783         if (r_refdef.fog_density && r_drawfog.integer)
6784         {
6785                 r_refdef.fogenabled = true;
6786                 // this is the point where the fog reaches 0.9986 alpha, which we
6787                 // consider a good enough cutoff point for the texture
6788                 // (0.9986 * 256 == 255.6)
6789                 if (r_fog_exp2.integer)
6790                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6791                 else
6792                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6793                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6794                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6795                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6796                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6797                         R_BuildFogHeightTexture();
6798                 // fog color was already set
6799                 // update the fog texture
6800                 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)
6801                         R_BuildFogTexture();
6802                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6803                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6804         }
6805         else
6806                 r_refdef.fogenabled = false;
6807
6808         // fog color
6809         if (r_refdef.fog_density)
6810         {
6811                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6812                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6813                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6814
6815                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6816                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6817                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6818                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6819
6820                 {
6821                         vec3_t fogvec;
6822                         VectorCopy(r_refdef.fogcolor, fogvec);
6823                         //   color.rgb *= ContrastBoost * SceneBrightness;
6824                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6825                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6826                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6827                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6828                 }
6829         }
6830 }
6831
6832 void R_UpdateVariables(void)
6833 {
6834         R_Textures_Frame();
6835
6836         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6837
6838         r_refdef.farclip = r_farclip_base.value;
6839         if (r_refdef.scene.worldmodel)
6840                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6841         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6842
6843         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6844                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6845         r_refdef.polygonfactor = 0;
6846         r_refdef.polygonoffset = 0;
6847         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6848         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6849
6850         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6851         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6852         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6853         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6854         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6855         if (FAKELIGHT_ENABLED)
6856         {
6857                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6858         }
6859         else if (r_refdef.scene.worldmodel)
6860         {
6861                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6862         }
6863         if (r_showsurfaces.integer)
6864         {
6865                 r_refdef.scene.rtworld = false;
6866                 r_refdef.scene.rtworldshadows = false;
6867                 r_refdef.scene.rtdlight = false;
6868                 r_refdef.scene.rtdlightshadows = false;
6869                 r_refdef.lightmapintensity = 0;
6870         }
6871
6872         switch(vid.renderpath)
6873         {
6874         case RENDERPATH_GL20:
6875         case RENDERPATH_D3D9:
6876         case RENDERPATH_D3D10:
6877         case RENDERPATH_D3D11:
6878         case RENDERPATH_SOFT:
6879         case RENDERPATH_GLES2:
6880                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6881                 {
6882                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6883                         {
6884                                 // build GLSL gamma texture
6885 #define RAMPWIDTH 256
6886                                 unsigned short ramp[RAMPWIDTH * 3];
6887                                 unsigned char rampbgr[RAMPWIDTH][4];
6888                                 int i;
6889
6890                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6891
6892                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6893                                 for(i = 0; i < RAMPWIDTH; ++i)
6894                                 {
6895                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6896                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6897                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6898                                         rampbgr[i][3] = 0;
6899                                 }
6900                                 if (r_texture_gammaramps)
6901                                 {
6902                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6903                                 }
6904                                 else
6905                                 {
6906                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6907                                 }
6908                         }
6909                 }
6910                 else
6911                 {
6912                         // remove GLSL gamma texture
6913                 }
6914                 break;
6915         case RENDERPATH_GL11:
6916         case RENDERPATH_GL13:
6917         case RENDERPATH_GLES1:
6918                 break;
6919         }
6920 }
6921
6922 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6923 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6924 /*
6925 ================
6926 R_SelectScene
6927 ================
6928 */
6929 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6930         if( scenetype != r_currentscenetype ) {
6931                 // store the old scenetype
6932                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6933                 r_currentscenetype = scenetype;
6934                 // move in the new scene
6935                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6936         }
6937 }
6938
6939 /*
6940 ================
6941 R_GetScenePointer
6942 ================
6943 */
6944 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6945 {
6946         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6947         if( scenetype == r_currentscenetype ) {
6948                 return &r_refdef.scene;
6949         } else {
6950                 return &r_scenes_store[ scenetype ];
6951         }
6952 }
6953
6954 static int R_SortEntities_Compare(const void *ap, const void *bp)
6955 {
6956         const entity_render_t *a = *(const entity_render_t **)ap;
6957         const entity_render_t *b = *(const entity_render_t **)bp;
6958
6959         // 1. compare model
6960         if(a->model < b->model)
6961                 return -1;
6962         if(a->model > b->model)
6963                 return +1;
6964
6965         // 2. compare skin
6966         // TODO possibly calculate the REAL skinnum here first using
6967         // skinscenes?
6968         if(a->skinnum < b->skinnum)
6969                 return -1;
6970         if(a->skinnum > b->skinnum)
6971                 return +1;
6972
6973         // everything we compared is equal
6974         return 0;
6975 }
6976 static void R_SortEntities(void)
6977 {
6978         // below or equal 2 ents, sorting never gains anything
6979         if(r_refdef.scene.numentities <= 2)
6980                 return;
6981         // sort
6982         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6983 }
6984
6985 /*
6986 ================
6987 R_RenderView
6988 ================
6989 */
6990 int dpsoftrast_test;
6991 extern cvar_t r_shadow_bouncegrid;
6992 void R_RenderView(void)
6993 {
6994         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6995         int fbo;
6996         rtexture_t *depthtexture;
6997         rtexture_t *colortexture;
6998
6999         dpsoftrast_test = r_test.integer;
7000
7001         if (r_timereport_active)
7002                 R_TimeReport("start");
7003         r_textureframe++; // used only by R_GetCurrentTexture
7004         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7005
7006         if(R_CompileShader_CheckStaticParms())
7007                 R_GLSL_Restart_f();
7008
7009         if (!r_drawentities.integer)
7010                 r_refdef.scene.numentities = 0;
7011         else if (r_sortentities.integer)
7012                 R_SortEntities();
7013
7014         R_AnimCache_ClearCache();
7015         R_FrameData_NewFrame();
7016
7017         /* adjust for stereo display */
7018         if(R_Stereo_Active())
7019         {
7020                 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);
7021                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7022         }
7023
7024         if (r_refdef.view.isoverlay)
7025         {
7026                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7027                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7028                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7029                 R_TimeReport("depthclear");
7030
7031                 r_refdef.view.showdebug = false;
7032
7033                 r_fb.water.enabled = false;
7034                 r_fb.water.numwaterplanes = 0;
7035
7036                 R_RenderScene(0, NULL, NULL);
7037
7038                 r_refdef.view.matrix = originalmatrix;
7039
7040                 CHECKGLERROR
7041                 return;
7042         }
7043
7044         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7045         {
7046                 r_refdef.view.matrix = originalmatrix;
7047                 return;
7048         }
7049
7050         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7051
7052         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7053                 // in sRGB fallback, behave similar to true sRGB: convert this
7054                 // value from linear to sRGB
7055                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7056
7057         R_RenderView_UpdateViewVectors();
7058
7059         R_Shadow_UpdateWorldLightSelection();
7060
7061         R_Bloom_StartFrame();
7062
7063         // apply bloom brightness offset
7064         if(r_fb.bloomtexture[0])
7065                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7066
7067         R_Water_StartFrame();
7068
7069         // now we probably have an fbo to render into
7070         fbo = r_fb.fbo;
7071         depthtexture = r_fb.depthtexture;
7072         colortexture = r_fb.colortexture;
7073
7074         CHECKGLERROR
7075         if (r_timereport_active)
7076                 R_TimeReport("viewsetup");
7077
7078         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7079
7080         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7081         {
7082                 R_ClearScreen(r_refdef.fogenabled);
7083                 if (r_timereport_active)
7084                         R_TimeReport("viewclear");
7085         }
7086         r_refdef.view.clear = true;
7087
7088         r_refdef.view.showdebug = true;
7089
7090         R_View_Update();
7091         if (r_timereport_active)
7092                 R_TimeReport("visibility");
7093
7094         R_AnimCache_CacheVisibleEntities();
7095         if (r_timereport_active)
7096                 R_TimeReport("animcache");
7097
7098         R_Shadow_UpdateBounceGridTexture();
7099         if (r_timereport_active && r_shadow_bouncegrid.integer)
7100                 R_TimeReport("bouncegrid");
7101
7102         r_fb.water.numwaterplanes = 0;
7103         if (r_fb.water.enabled)
7104                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7105
7106         R_RenderScene(fbo, depthtexture, colortexture);
7107         r_fb.water.numwaterplanes = 0;
7108
7109         R_BlendView(fbo, depthtexture, colortexture);
7110         if (r_timereport_active)
7111                 R_TimeReport("blendview");
7112
7113         GL_Scissor(0, 0, vid.width, vid.height);
7114         GL_ScissorTest(false);
7115
7116         r_refdef.view.matrix = originalmatrix;
7117
7118         CHECKGLERROR
7119 }
7120
7121 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7122 {
7123         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7124         {
7125                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7126                 if (r_timereport_active)
7127                         R_TimeReport("waterworld");
7128         }
7129
7130         // don't let sound skip if going slow
7131         if (r_refdef.scene.extraupdate)
7132                 S_ExtraUpdate ();
7133
7134         R_DrawModelsAddWaterPlanes();
7135         if (r_timereport_active)
7136                 R_TimeReport("watermodels");
7137
7138         if (r_fb.water.numwaterplanes)
7139         {
7140                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7141                 if (r_timereport_active)
7142                         R_TimeReport("waterscenes");
7143         }
7144 }
7145
7146 extern cvar_t cl_locs_show;
7147 static void R_DrawLocs(void);
7148 static void R_DrawEntityBBoxes(void);
7149 static void R_DrawModelDecals(void);
7150 extern cvar_t cl_decals_newsystem;
7151 extern qboolean r_shadow_usingdeferredprepass;
7152 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7153 {
7154         qboolean shadowmapping = false;
7155
7156         if (r_timereport_active)
7157                 R_TimeReport("beginscene");
7158
7159         r_refdef.stats.renders++;
7160
7161         R_UpdateFog();
7162
7163         // don't let sound skip if going slow
7164         if (r_refdef.scene.extraupdate)
7165                 S_ExtraUpdate ();
7166
7167         R_MeshQueue_BeginScene();
7168
7169         R_SkyStartFrame();
7170
7171         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);
7172
7173         if (r_timereport_active)
7174                 R_TimeReport("skystartframe");
7175
7176         if (cl.csqc_vidvars.drawworld)
7177         {
7178                 // don't let sound skip if going slow
7179                 if (r_refdef.scene.extraupdate)
7180                         S_ExtraUpdate ();
7181
7182                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7183                 {
7184                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7185                         if (r_timereport_active)
7186                                 R_TimeReport("worldsky");
7187                 }
7188
7189                 if (R_DrawBrushModelsSky() && r_timereport_active)
7190                         R_TimeReport("bmodelsky");
7191
7192                 if (skyrendermasked && skyrenderlater)
7193                 {
7194                         // we have to force off the water clipping plane while rendering sky
7195                         R_SetupView(false, fbo, depthtexture, colortexture);
7196                         R_Sky();
7197                         R_SetupView(true, fbo, depthtexture, colortexture);
7198                         if (r_timereport_active)
7199                                 R_TimeReport("sky");
7200                 }
7201         }
7202
7203         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7204         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7205                 R_Shadow_PrepareModelShadows();
7206         if (r_timereport_active)
7207                 R_TimeReport("preparelights");
7208
7209         if (R_Shadow_ShadowMappingEnabled())
7210                 shadowmapping = true;
7211
7212         if (r_shadow_usingdeferredprepass)
7213                 R_Shadow_DrawPrepass();
7214
7215         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7216         {
7217                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7218                 if (r_timereport_active)
7219                         R_TimeReport("worlddepth");
7220         }
7221         if (r_depthfirst.integer >= 2)
7222         {
7223                 R_DrawModelsDepth();
7224                 if (r_timereport_active)
7225                         R_TimeReport("modeldepth");
7226         }
7227
7228         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7229         {
7230                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7231                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7232                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7233                 // don't let sound skip if going slow
7234                 if (r_refdef.scene.extraupdate)
7235                         S_ExtraUpdate ();
7236         }
7237
7238         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7239         {
7240                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7241                 if (r_timereport_active)
7242                         R_TimeReport("world");
7243         }
7244
7245         // don't let sound skip if going slow
7246         if (r_refdef.scene.extraupdate)
7247                 S_ExtraUpdate ();
7248
7249         R_DrawModels();
7250         if (r_timereport_active)
7251                 R_TimeReport("models");
7252
7253         // don't let sound skip if going slow
7254         if (r_refdef.scene.extraupdate)
7255                 S_ExtraUpdate ();
7256
7257         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7258         {
7259                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7260                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7261                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7262                 // don't let sound skip if going slow
7263                 if (r_refdef.scene.extraupdate)
7264                         S_ExtraUpdate ();
7265         }
7266
7267         if (!r_shadow_usingdeferredprepass)
7268         {
7269                 R_Shadow_DrawLights();
7270                 if (r_timereport_active)
7271                         R_TimeReport("rtlights");
7272         }
7273
7274         // don't let sound skip if going slow
7275         if (r_refdef.scene.extraupdate)
7276                 S_ExtraUpdate ();
7277
7278         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7279         {
7280                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7281                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7282                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7283                 // don't let sound skip if going slow
7284                 if (r_refdef.scene.extraupdate)
7285                         S_ExtraUpdate ();
7286         }
7287
7288         if (cl.csqc_vidvars.drawworld)
7289         {
7290                 if (cl_decals_newsystem.integer)
7291                 {
7292                         R_DrawModelDecals();
7293                         if (r_timereport_active)
7294                                 R_TimeReport("modeldecals");
7295                 }
7296                 else
7297                 {
7298                         R_DrawDecals();
7299                         if (r_timereport_active)
7300                                 R_TimeReport("decals");
7301                 }
7302
7303                 R_DrawParticles();
7304                 if (r_timereport_active)
7305                         R_TimeReport("particles");
7306
7307                 R_DrawExplosions();
7308                 if (r_timereport_active)
7309                         R_TimeReport("explosions");
7310
7311                 R_DrawLightningBeams();
7312                 if (r_timereport_active)
7313                         R_TimeReport("lightning");
7314         }
7315
7316         if (cl.csqc_loaded)
7317                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7318
7319         if (r_refdef.view.showdebug)
7320         {
7321                 if (cl_locs_show.integer)
7322                 {
7323                         R_DrawLocs();
7324                         if (r_timereport_active)
7325                                 R_TimeReport("showlocs");
7326                 }
7327
7328                 if (r_drawportals.integer)
7329                 {
7330                         R_DrawPortals();
7331                         if (r_timereport_active)
7332                                 R_TimeReport("portals");
7333                 }
7334
7335                 if (r_showbboxes.value > 0)
7336                 {
7337                         R_DrawEntityBBoxes();
7338                         if (r_timereport_active)
7339                                 R_TimeReport("bboxes");
7340                 }
7341         }
7342
7343         if (r_transparent.integer)
7344         {
7345                 R_MeshQueue_RenderTransparent();
7346                 if (r_timereport_active)
7347                         R_TimeReport("drawtrans");
7348         }
7349
7350         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))
7351         {
7352                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7353                 if (r_timereport_active)
7354                         R_TimeReport("worlddebug");
7355                 R_DrawModelsDebug();
7356                 if (r_timereport_active)
7357                         R_TimeReport("modeldebug");
7358         }
7359
7360         if (cl.csqc_vidvars.drawworld)
7361         {
7362                 R_Shadow_DrawCoronas();
7363                 if (r_timereport_active)
7364                         R_TimeReport("coronas");
7365         }
7366
7367 #if 0
7368         {
7369                 GL_DepthTest(false);
7370                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7371                 GL_Color(1, 1, 1, 1);
7372                 qglBegin(GL_POLYGON);
7373                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7374                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7375                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7376                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7377                 qglEnd();
7378                 qglBegin(GL_POLYGON);
7379                 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]);
7380                 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]);
7381                 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]);
7382                 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]);
7383                 qglEnd();
7384                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7385         }
7386 #endif
7387
7388         // don't let sound skip if going slow
7389         if (r_refdef.scene.extraupdate)
7390                 S_ExtraUpdate ();
7391 }
7392
7393 static const unsigned short bboxelements[36] =
7394 {
7395         5, 1, 3, 5, 3, 7,
7396         6, 2, 0, 6, 0, 4,
7397         7, 3, 2, 7, 2, 6,
7398         4, 0, 1, 4, 1, 5,
7399         4, 5, 7, 4, 7, 6,
7400         1, 0, 2, 1, 2, 3,
7401 };
7402
7403 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7404 {
7405         int i;
7406         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7407
7408         RSurf_ActiveWorldEntity();
7409
7410         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7411         GL_DepthMask(false);
7412         GL_DepthRange(0, 1);
7413         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7414 //      R_Mesh_ResetTextureState();
7415
7416         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7417         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7418         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7419         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7420         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7421         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7422         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7423         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7424         R_FillColors(color4f, 8, cr, cg, cb, ca);
7425         if (r_refdef.fogenabled)
7426         {
7427                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7428                 {
7429                         f1 = RSurf_FogVertex(v);
7430                         f2 = 1 - f1;
7431                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7432                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7433                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7434                 }
7435         }
7436         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7437         R_Mesh_ResetTextureState();
7438         R_SetupShader_Generic_NoTexture(false, false);
7439         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7440 }
7441
7442 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7443 {
7444         prvm_prog_t *prog = SVVM_prog;
7445         int i;
7446         float color[4];
7447         prvm_edict_t *edict;
7448
7449         // this function draws bounding boxes of server entities
7450         if (!sv.active)
7451                 return;
7452
7453         GL_CullFace(GL_NONE);
7454         R_SetupShader_Generic_NoTexture(false, false);
7455
7456         for (i = 0;i < numsurfaces;i++)
7457         {
7458                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7459                 switch ((int)PRVM_serveredictfloat(edict, solid))
7460                 {
7461                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7462                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7463                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7464                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7465                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7466                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7467                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7468                 }
7469                 color[3] *= r_showbboxes.value;
7470                 color[3] = bound(0, color[3], 1);
7471                 GL_DepthTest(!r_showdisabledepthtest.integer);
7472                 GL_CullFace(r_refdef.view.cullface_front);
7473                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7474         }
7475 }
7476
7477 static void R_DrawEntityBBoxes(void)
7478 {
7479         int i;
7480         prvm_edict_t *edict;
7481         vec3_t center;
7482         prvm_prog_t *prog = SVVM_prog;
7483
7484         // this function draws bounding boxes of server entities
7485         if (!sv.active)
7486                 return;
7487
7488         for (i = 0;i < prog->num_edicts;i++)
7489         {
7490                 edict = PRVM_EDICT_NUM(i);
7491                 if (edict->priv.server->free)
7492                         continue;
7493                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7494                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7495                         continue;
7496                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7497                         continue;
7498                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7499                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7500         }
7501 }
7502
7503 static const int nomodelelement3i[24] =
7504 {
7505         5, 2, 0,
7506         5, 1, 2,
7507         5, 0, 3,
7508         5, 3, 1,
7509         0, 2, 4,
7510         2, 1, 4,
7511         3, 0, 4,
7512         1, 3, 4
7513 };
7514
7515 static const unsigned short nomodelelement3s[24] =
7516 {
7517         5, 2, 0,
7518         5, 1, 2,
7519         5, 0, 3,
7520         5, 3, 1,
7521         0, 2, 4,
7522         2, 1, 4,
7523         3, 0, 4,
7524         1, 3, 4
7525 };
7526
7527 static const float nomodelvertex3f[6*3] =
7528 {
7529         -16,   0,   0,
7530          16,   0,   0,
7531           0, -16,   0,
7532           0,  16,   0,
7533           0,   0, -16,
7534           0,   0,  16
7535 };
7536
7537 static const float nomodelcolor4f[6*4] =
7538 {
7539         0.0f, 0.0f, 0.5f, 1.0f,
7540         0.0f, 0.0f, 0.5f, 1.0f,
7541         0.0f, 0.5f, 0.0f, 1.0f,
7542         0.0f, 0.5f, 0.0f, 1.0f,
7543         0.5f, 0.0f, 0.0f, 1.0f,
7544         0.5f, 0.0f, 0.0f, 1.0f
7545 };
7546
7547 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7548 {
7549         int i;
7550         float f1, f2, *c;
7551         float color4f[6*4];
7552
7553         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);
7554
7555         // this is only called once per entity so numsurfaces is always 1, and
7556         // surfacelist is always {0}, so this code does not handle batches
7557
7558         if (rsurface.ent_flags & RENDER_ADDITIVE)
7559         {
7560                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7561                 GL_DepthMask(false);
7562         }
7563         else if (rsurface.colormod[3] < 1)
7564         {
7565                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7566                 GL_DepthMask(false);
7567         }
7568         else
7569         {
7570                 GL_BlendFunc(GL_ONE, GL_ZERO);
7571                 GL_DepthMask(true);
7572         }
7573         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7574         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7575         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7576         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7577         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7578         for (i = 0, c = color4f;i < 6;i++, c += 4)
7579         {
7580                 c[0] *= rsurface.colormod[0];
7581                 c[1] *= rsurface.colormod[1];
7582                 c[2] *= rsurface.colormod[2];
7583                 c[3] *= rsurface.colormod[3];
7584         }
7585         if (r_refdef.fogenabled)
7586         {
7587                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7588                 {
7589                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7590                         f2 = 1 - f1;
7591                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7592                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7593                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7594                 }
7595         }
7596 //      R_Mesh_ResetTextureState();
7597         R_SetupShader_Generic_NoTexture(false, false);
7598         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7599         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7600 }
7601
7602 void R_DrawNoModel(entity_render_t *ent)
7603 {
7604         vec3_t org;
7605         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7606         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7607                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7608         else
7609                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7610 }
7611
7612 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7613 {
7614         vec3_t right1, right2, diff, normal;
7615
7616         VectorSubtract (org2, org1, normal);
7617
7618         // calculate 'right' vector for start
7619         VectorSubtract (r_refdef.view.origin, org1, diff);
7620         CrossProduct (normal, diff, right1);
7621         VectorNormalize (right1);
7622
7623         // calculate 'right' vector for end
7624         VectorSubtract (r_refdef.view.origin, org2, diff);
7625         CrossProduct (normal, diff, right2);
7626         VectorNormalize (right2);
7627
7628         vert[ 0] = org1[0] + width * right1[0];
7629         vert[ 1] = org1[1] + width * right1[1];
7630         vert[ 2] = org1[2] + width * right1[2];
7631         vert[ 3] = org1[0] - width * right1[0];
7632         vert[ 4] = org1[1] - width * right1[1];
7633         vert[ 5] = org1[2] - width * right1[2];
7634         vert[ 6] = org2[0] - width * right2[0];
7635         vert[ 7] = org2[1] - width * right2[1];
7636         vert[ 8] = org2[2] - width * right2[2];
7637         vert[ 9] = org2[0] + width * right2[0];
7638         vert[10] = org2[1] + width * right2[1];
7639         vert[11] = org2[2] + width * right2[2];
7640 }
7641
7642 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)
7643 {
7644         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7645         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7646         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7647         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7648         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7649         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7650         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7651         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7652         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7653         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7654         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7655         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7656 }
7657
7658 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7659 {
7660         int i;
7661         float *vertex3f;
7662         float v[3];
7663         VectorSet(v, x, y, z);
7664         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7665                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7666                         break;
7667         if (i == mesh->numvertices)
7668         {
7669                 if (mesh->numvertices < mesh->maxvertices)
7670                 {
7671                         VectorCopy(v, vertex3f);
7672                         mesh->numvertices++;
7673                 }
7674                 return mesh->numvertices;
7675         }
7676         else
7677                 return i;
7678 }
7679
7680 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7681 {
7682         int i;
7683         int *e, element[3];
7684         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7685         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7686         e = mesh->element3i + mesh->numtriangles * 3;
7687         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7688         {
7689                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7690                 if (mesh->numtriangles < mesh->maxtriangles)
7691                 {
7692                         *e++ = element[0];
7693                         *e++ = element[1];
7694                         *e++ = element[2];
7695                         mesh->numtriangles++;
7696                 }
7697                 element[1] = element[2];
7698         }
7699 }
7700
7701 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7702 {
7703         int i;
7704         int *e, element[3];
7705         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7706         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7707         e = mesh->element3i + mesh->numtriangles * 3;
7708         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7709         {
7710                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7711                 if (mesh->numtriangles < mesh->maxtriangles)
7712                 {
7713                         *e++ = element[0];
7714                         *e++ = element[1];
7715                         *e++ = element[2];
7716                         mesh->numtriangles++;
7717                 }
7718                 element[1] = element[2];
7719         }
7720 }
7721
7722 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7723 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7724 {
7725         int planenum, planenum2;
7726         int w;
7727         int tempnumpoints;
7728         mplane_t *plane, *plane2;
7729         double maxdist;
7730         double temppoints[2][256*3];
7731         // figure out how large a bounding box we need to properly compute this brush
7732         maxdist = 0;
7733         for (w = 0;w < numplanes;w++)
7734                 maxdist = max(maxdist, fabs(planes[w].dist));
7735         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7736         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7737         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7738         {
7739                 w = 0;
7740                 tempnumpoints = 4;
7741                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7742                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7743                 {
7744                         if (planenum2 == planenum)
7745                                 continue;
7746                         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);
7747                         w = !w;
7748                 }
7749                 if (tempnumpoints < 3)
7750                         continue;
7751                 // generate elements forming a triangle fan for this polygon
7752                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7753         }
7754 }
7755
7756 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)
7757 {
7758         texturelayer_t *layer;
7759         layer = t->currentlayers + t->currentnumlayers++;
7760         layer->type = type;
7761         layer->depthmask = depthmask;
7762         layer->blendfunc1 = blendfunc1;
7763         layer->blendfunc2 = blendfunc2;
7764         layer->texture = texture;
7765         layer->texmatrix = *matrix;
7766         layer->color[0] = r;
7767         layer->color[1] = g;
7768         layer->color[2] = b;
7769         layer->color[3] = a;
7770 }
7771
7772 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7773 {
7774         if(parms[0] == 0 && parms[1] == 0)
7775                 return false;
7776         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7777                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7778                         return false;
7779         return true;
7780 }
7781
7782 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7783 {
7784         double index, f;
7785         index = parms[2] + rsurface.shadertime * parms[3];
7786         index -= floor(index);
7787         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7788         {
7789         default:
7790         case Q3WAVEFUNC_NONE:
7791         case Q3WAVEFUNC_NOISE:
7792         case Q3WAVEFUNC_COUNT:
7793                 f = 0;
7794                 break;
7795         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7796         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7797         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7798         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7799         case Q3WAVEFUNC_TRIANGLE:
7800                 index *= 4;
7801                 f = index - floor(index);
7802                 if (index < 1)
7803                 {
7804                         // f = f;
7805                 }
7806                 else if (index < 2)
7807                         f = 1 - f;
7808                 else if (index < 3)
7809                         f = -f;
7810                 else
7811                         f = -(1 - f);
7812                 break;
7813         }
7814         f = parms[0] + parms[1] * f;
7815         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7816                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7817         return (float) f;
7818 }
7819
7820 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7821 {
7822         int w, h, idx;
7823         double f;
7824         double offsetd[2];
7825         float tcmat[12];
7826         matrix4x4_t matrix, temp;
7827         switch(tcmod->tcmod)
7828         {
7829                 case Q3TCMOD_COUNT:
7830                 case Q3TCMOD_NONE:
7831                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7832                                 matrix = r_waterscrollmatrix;
7833                         else
7834                                 matrix = identitymatrix;
7835                         break;
7836                 case Q3TCMOD_ENTITYTRANSLATE:
7837                         // this is used in Q3 to allow the gamecode to control texcoord
7838                         // scrolling on the entity, which is not supported in darkplaces yet.
7839                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7840                         break;
7841                 case Q3TCMOD_ROTATE:
7842                         f = tcmod->parms[0] * rsurface.shadertime;
7843                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7844                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7845                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7846                         break;
7847                 case Q3TCMOD_SCALE:
7848                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7849                         break;
7850                 case Q3TCMOD_SCROLL:
7851                         // extra care is needed because of precision breakdown with large values of time
7852                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7853                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7854                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7855                         break;
7856                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7857                         w = (int) tcmod->parms[0];
7858                         h = (int) tcmod->parms[1];
7859                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7860                         f = f - floor(f);
7861                         idx = (int) floor(f * w * h);
7862                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7863                         break;
7864                 case Q3TCMOD_STRETCH:
7865                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7866                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7867                         break;
7868                 case Q3TCMOD_TRANSFORM:
7869                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7870                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7871                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7872                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7873                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7874                         break;
7875                 case Q3TCMOD_TURBULENT:
7876                         // this is handled in the RSurf_PrepareVertices function
7877                         matrix = identitymatrix;
7878                         break;
7879         }
7880         temp = *texmatrix;
7881         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7882 }
7883
7884 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7885 {
7886         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7887         char name[MAX_QPATH];
7888         skinframe_t *skinframe;
7889         unsigned char pixels[296*194];
7890         strlcpy(cache->name, skinname, sizeof(cache->name));
7891         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7892         if (developer_loading.integer)
7893                 Con_Printf("loading %s\n", name);
7894         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7895         if (!skinframe || !skinframe->base)
7896         {
7897                 unsigned char *f;
7898                 fs_offset_t filesize;
7899                 skinframe = NULL;
7900                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7901                 if (f)
7902                 {
7903                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7904                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7905                         Mem_Free(f);
7906                 }
7907         }
7908         cache->skinframe = skinframe;
7909 }
7910
7911 texture_t *R_GetCurrentTexture(texture_t *t)
7912 {
7913         int i;
7914         const entity_render_t *ent = rsurface.entity;
7915         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7916         q3shaderinfo_layer_tcmod_t *tcmod;
7917
7918         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7919                 return t->currentframe;
7920         t->update_lastrenderframe = r_textureframe;
7921         t->update_lastrenderentity = (void *)ent;
7922
7923         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7924                 t->camera_entity = ent->entitynumber;
7925         else
7926                 t->camera_entity = 0;
7927
7928         // switch to an alternate material if this is a q1bsp animated material
7929         {
7930                 texture_t *texture = t;
7931                 int s = rsurface.ent_skinnum;
7932                 if ((unsigned int)s >= (unsigned int)model->numskins)
7933                         s = 0;
7934                 if (model->skinscenes)
7935                 {
7936                         if (model->skinscenes[s].framecount > 1)
7937                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7938                         else
7939                                 s = model->skinscenes[s].firstframe;
7940                 }
7941                 if (s > 0)
7942                         t = t + s * model->num_surfaces;
7943                 if (t->animated)
7944                 {
7945                         // use an alternate animation if the entity's frame is not 0,
7946                         // and only if the texture has an alternate animation
7947                         if (rsurface.ent_alttextures && t->anim_total[1])
7948                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7949                         else
7950                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7951                 }
7952                 texture->currentframe = t;
7953         }
7954
7955         // update currentskinframe to be a qw skin or animation frame
7956         if (rsurface.ent_qwskin >= 0)
7957         {
7958                 i = rsurface.ent_qwskin;
7959                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7960                 {
7961                         r_qwskincache_size = cl.maxclients;
7962                         if (r_qwskincache)
7963                                 Mem_Free(r_qwskincache);
7964                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7965                 }
7966                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7967                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7968                 t->currentskinframe = r_qwskincache[i].skinframe;
7969                 if (t->currentskinframe == NULL)
7970                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7971         }
7972         else if (t->numskinframes >= 2)
7973                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7974         if (t->backgroundnumskinframes >= 2)
7975                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7976
7977         t->currentmaterialflags = t->basematerialflags;
7978         t->currentalpha = rsurface.colormod[3];
7979         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7980                 t->currentalpha *= r_wateralpha.value;
7981         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7982                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7983         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7984                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7985         if (!(rsurface.ent_flags & RENDER_LIGHT))
7986                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7987         else if (FAKELIGHT_ENABLED)
7988         {
7989                 // no modellight if using fakelight for the map
7990         }
7991         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7992         {
7993                 // pick a model lighting mode
7994                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7995                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7996                 else
7997                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7998         }
7999         if (rsurface.ent_flags & RENDER_ADDITIVE)
8000                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8001         else if (t->currentalpha < 1)
8002                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8003         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8004         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8005                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8006         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8007                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8008         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8009                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8010         if (t->backgroundnumskinframes)
8011                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8012         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8013         {
8014                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8015                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8016         }
8017         else
8018                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8019         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8020         {
8021                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8022                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8023         }
8024         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8025                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8026
8027         // there is no tcmod
8028         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8029         {
8030                 t->currenttexmatrix = r_waterscrollmatrix;
8031                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8032         }
8033         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8034         {
8035                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8036                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8037         }
8038
8039         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8040                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8041         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8042                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8043
8044         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8045         if (t->currentskinframe->qpixels)
8046                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8047         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8048         if (!t->basetexture)
8049                 t->basetexture = r_texture_notexture;
8050         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8051         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8052         t->nmaptexture = t->currentskinframe->nmap;
8053         if (!t->nmaptexture)
8054                 t->nmaptexture = r_texture_blanknormalmap;
8055         t->glosstexture = r_texture_black;
8056         t->glowtexture = t->currentskinframe->glow;
8057         t->fogtexture = t->currentskinframe->fog;
8058         t->reflectmasktexture = t->currentskinframe->reflect;
8059         if (t->backgroundnumskinframes)
8060         {
8061                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8062                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8063                 t->backgroundglosstexture = r_texture_black;
8064                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8065                 if (!t->backgroundnmaptexture)
8066                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8067                 // make sure that if glow is going to be used, both textures are not NULL
8068                 if (!t->backgroundglowtexture && t->glowtexture)
8069                         t->backgroundglowtexture = r_texture_black;
8070                 if (!t->glowtexture && t->backgroundglowtexture)
8071                         t->glowtexture = r_texture_black;
8072         }
8073         else
8074         {
8075                 t->backgroundbasetexture = r_texture_white;
8076                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8077                 t->backgroundglosstexture = r_texture_black;
8078                 t->backgroundglowtexture = NULL;
8079         }
8080         t->specularpower = r_shadow_glossexponent.value;
8081         // TODO: store reference values for these in the texture?
8082         t->specularscale = 0;
8083         if (r_shadow_gloss.integer > 0)
8084         {
8085                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8086                 {
8087                         if (r_shadow_glossintensity.value > 0)
8088                         {
8089                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8090                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8091                                 t->specularscale = r_shadow_glossintensity.value;
8092                         }
8093                 }
8094                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8095                 {
8096                         t->glosstexture = r_texture_white;
8097                         t->backgroundglosstexture = r_texture_white;
8098                         t->specularscale = r_shadow_gloss2intensity.value;
8099                         t->specularpower = r_shadow_gloss2exponent.value;
8100                 }
8101         }
8102         t->specularscale *= t->specularscalemod;
8103         t->specularpower *= t->specularpowermod;
8104         t->rtlightambient = 0;
8105
8106         // lightmaps mode looks bad with dlights using actual texturing, so turn
8107         // off the colormap and glossmap, but leave the normalmap on as it still
8108         // accurately represents the shading involved
8109         if (gl_lightmaps.integer)
8110         {
8111                 t->basetexture = r_texture_grey128;
8112                 t->pantstexture = r_texture_black;
8113                 t->shirttexture = r_texture_black;
8114                 if (gl_lightmaps.integer < 2)
8115                         t->nmaptexture = r_texture_blanknormalmap;
8116                 t->glosstexture = r_texture_black;
8117                 t->glowtexture = NULL;
8118                 t->fogtexture = NULL;
8119                 t->reflectmasktexture = NULL;
8120                 t->backgroundbasetexture = NULL;
8121                 if (gl_lightmaps.integer < 2)
8122                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8123                 t->backgroundglosstexture = r_texture_black;
8124                 t->backgroundglowtexture = NULL;
8125                 t->specularscale = 0;
8126                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8127         }
8128
8129         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8130         VectorClear(t->dlightcolor);
8131         t->currentnumlayers = 0;
8132         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8133         {
8134                 int blendfunc1, blendfunc2;
8135                 qboolean depthmask;
8136                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8137                 {
8138                         blendfunc1 = GL_SRC_ALPHA;
8139                         blendfunc2 = GL_ONE;
8140                 }
8141                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8142                 {
8143                         blendfunc1 = GL_SRC_ALPHA;
8144                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8145                 }
8146                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8147                 {
8148                         blendfunc1 = t->customblendfunc[0];
8149                         blendfunc2 = t->customblendfunc[1];
8150                 }
8151                 else
8152                 {
8153                         blendfunc1 = GL_ONE;
8154                         blendfunc2 = GL_ZERO;
8155                 }
8156                 // don't colormod evilblend textures
8157                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8158                         VectorSet(t->lightmapcolor, 1, 1, 1);
8159                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8160                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8161                 {
8162                         // fullbright is not affected by r_refdef.lightmapintensity
8163                         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]);
8164                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8165                                 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]);
8166                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8167                                 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]);
8168                 }
8169                 else
8170                 {
8171                         vec3_t ambientcolor;
8172                         float colorscale;
8173                         // set the color tint used for lights affecting this surface
8174                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8175                         colorscale = 2;
8176                         // q3bsp has no lightmap updates, so the lightstylevalue that
8177                         // would normally be baked into the lightmap must be
8178                         // applied to the color
8179                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8180                         if (model->type == mod_brushq3)
8181                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8182                         colorscale *= r_refdef.lightmapintensity;
8183                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8184                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8185                         // basic lit geometry
8186                         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]);
8187                         // add pants/shirt if needed
8188                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8189                                 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]);
8190                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8191                                 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]);
8192                         // now add ambient passes if needed
8193                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8194                         {
8195                                 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]);
8196                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8197                                         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]);
8198                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8199                                         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]);
8200                         }
8201                 }
8202                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8203                         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]);
8204                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8205                 {
8206                         // if this is opaque use alpha blend which will darken the earlier
8207                         // passes cheaply.
8208                         //
8209                         // if this is an alpha blended material, all the earlier passes
8210                         // were darkened by fog already, so we only need to add the fog
8211                         // color ontop through the fog mask texture
8212                         //
8213                         // if this is an additive blended material, all the earlier passes
8214                         // were darkened by fog already, and we should not add fog color
8215                         // (because the background was not darkened, there is no fog color
8216                         // that was lost behind it).
8217                         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]);
8218                 }
8219         }
8220
8221         return t->currentframe;
8222 }
8223
8224 rsurfacestate_t rsurface;
8225
8226 void RSurf_ActiveWorldEntity(void)
8227 {
8228         dp_model_t *model = r_refdef.scene.worldmodel;
8229         //if (rsurface.entity == r_refdef.scene.worldentity)
8230         //      return;
8231         rsurface.entity = r_refdef.scene.worldentity;
8232         rsurface.skeleton = NULL;
8233         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8234         rsurface.ent_skinnum = 0;
8235         rsurface.ent_qwskin = -1;
8236         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8237         rsurface.shadertime = r_refdef.scene.time;
8238         rsurface.matrix = identitymatrix;
8239         rsurface.inversematrix = identitymatrix;
8240         rsurface.matrixscale = 1;
8241         rsurface.inversematrixscale = 1;
8242         R_EntityMatrix(&identitymatrix);
8243         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8244         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8245         rsurface.fograngerecip = r_refdef.fograngerecip;
8246         rsurface.fogheightfade = r_refdef.fogheightfade;
8247         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8248         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8249         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8250         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8251         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8252         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8253         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8254         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8255         rsurface.colormod[3] = 1;
8256         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);
8257         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8258         rsurface.frameblend[0].lerp = 1;
8259         rsurface.ent_alttextures = false;
8260         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8261         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8262         rsurface.entityskeletaltransform3x4 = NULL;
8263         rsurface.entityskeletalnumtransforms = 0;
8264         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8265         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8266         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8267         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8268         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8269         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8270         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8271         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8272         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8273         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8274         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8275         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8276         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8277         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8278         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8279         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8280         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8281         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8282         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8283         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8284         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8285         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8286         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8287         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8288         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8289         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8290         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8291         rsurface.modelelement3i = model->surfmesh.data_element3i;
8292         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8293         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8294         rsurface.modelelement3s = model->surfmesh.data_element3s;
8295         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8296         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8297         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8298         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8299         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8300         rsurface.modelsurfaces = model->data_surfaces;
8301         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8302         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8303         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8304         rsurface.modelgeneratedvertex = false;
8305         rsurface.batchgeneratedvertex = false;
8306         rsurface.batchfirstvertex = 0;
8307         rsurface.batchnumvertices = 0;
8308         rsurface.batchfirsttriangle = 0;
8309         rsurface.batchnumtriangles = 0;
8310         rsurface.batchvertex3f  = NULL;
8311         rsurface.batchvertex3f_vertexbuffer = NULL;
8312         rsurface.batchvertex3f_bufferoffset = 0;
8313         rsurface.batchsvector3f = NULL;
8314         rsurface.batchsvector3f_vertexbuffer = NULL;
8315         rsurface.batchsvector3f_bufferoffset = 0;
8316         rsurface.batchtvector3f = NULL;
8317         rsurface.batchtvector3f_vertexbuffer = NULL;
8318         rsurface.batchtvector3f_bufferoffset = 0;
8319         rsurface.batchnormal3f  = NULL;
8320         rsurface.batchnormal3f_vertexbuffer = NULL;
8321         rsurface.batchnormal3f_bufferoffset = 0;
8322         rsurface.batchlightmapcolor4f = NULL;
8323         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8324         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8325         rsurface.batchtexcoordtexture2f = NULL;
8326         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8327         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8328         rsurface.batchtexcoordlightmap2f = NULL;
8329         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8330         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8331         rsurface.batchskeletalindex4ub = NULL;
8332         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8333         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8334         rsurface.batchskeletalweight4ub = NULL;
8335         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8336         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8337         rsurface.batchvertexmesh = NULL;
8338         rsurface.batchvertexmeshbuffer = NULL;
8339         rsurface.batchvertex3fbuffer = NULL;
8340         rsurface.batchelement3i = NULL;
8341         rsurface.batchelement3i_indexbuffer = NULL;
8342         rsurface.batchelement3i_bufferoffset = 0;
8343         rsurface.batchelement3s = NULL;
8344         rsurface.batchelement3s_indexbuffer = NULL;
8345         rsurface.batchelement3s_bufferoffset = 0;
8346         rsurface.passcolor4f = NULL;
8347         rsurface.passcolor4f_vertexbuffer = NULL;
8348         rsurface.passcolor4f_bufferoffset = 0;
8349         rsurface.forcecurrenttextureupdate = false;
8350 }
8351
8352 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8353 {
8354         dp_model_t *model = ent->model;
8355         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8356         //      return;
8357         rsurface.entity = (entity_render_t *)ent;
8358         rsurface.skeleton = ent->skeleton;
8359         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8360         rsurface.ent_skinnum = ent->skinnum;
8361         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;
8362         rsurface.ent_flags = ent->flags;
8363         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8364         rsurface.matrix = ent->matrix;
8365         rsurface.inversematrix = ent->inversematrix;
8366         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8367         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8368         R_EntityMatrix(&rsurface.matrix);
8369         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8370         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8371         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8372         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8373         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8374         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8375         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8376         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8377         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8378         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8379         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8380         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8381         rsurface.colormod[3] = ent->alpha;
8382         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8383         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8384         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8385         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8386         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8387         if (ent->model->brush.submodel && !prepass)
8388         {
8389                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8390                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8391         }
8392         // if the animcache code decided it should use the shader path, skip the deform step
8393         rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8394         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8395         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8396         {
8397                 if (ent->animcache_vertex3f)
8398                 {
8399                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8400                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8401                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8402                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8403                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8404                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8405                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8406                 }
8407                 else if (wanttangents)
8408                 {
8409                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8410                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8411                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8412                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8413                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8414                         rsurface.modelvertexmesh = NULL;
8415                         rsurface.modelvertexmeshbuffer = NULL;
8416                         rsurface.modelvertex3fbuffer = NULL;
8417                 }
8418                 else if (wantnormals)
8419                 {
8420                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8421                         rsurface.modelsvector3f = NULL;
8422                         rsurface.modeltvector3f = NULL;
8423                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8424                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8425                         rsurface.modelvertexmesh = NULL;
8426                         rsurface.modelvertexmeshbuffer = NULL;
8427                         rsurface.modelvertex3fbuffer = NULL;
8428                 }
8429                 else
8430                 {
8431                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8432                         rsurface.modelsvector3f = NULL;
8433                         rsurface.modeltvector3f = NULL;
8434                         rsurface.modelnormal3f = NULL;
8435                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8436                         rsurface.modelvertexmesh = NULL;
8437                         rsurface.modelvertexmeshbuffer = NULL;
8438                         rsurface.modelvertex3fbuffer = NULL;
8439                 }
8440                 rsurface.modelvertex3f_vertexbuffer = 0;
8441                 rsurface.modelvertex3f_bufferoffset = 0;
8442                 rsurface.modelsvector3f_vertexbuffer = 0;
8443                 rsurface.modelsvector3f_bufferoffset = 0;
8444                 rsurface.modeltvector3f_vertexbuffer = 0;
8445                 rsurface.modeltvector3f_bufferoffset = 0;
8446                 rsurface.modelnormal3f_vertexbuffer = 0;
8447                 rsurface.modelnormal3f_bufferoffset = 0;
8448                 rsurface.modelgeneratedvertex = true;
8449         }
8450         else
8451         {
8452                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8453                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8454                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8455                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8456                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8457                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8458                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8459                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8460                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8461                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8462                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8463                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8464                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8465                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8466                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8467                 rsurface.modelgeneratedvertex = false;
8468         }
8469         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8470         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8471         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8472         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8473         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8475         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8476         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8478         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8479         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8481         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8482         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8484         rsurface.modelelement3i = model->surfmesh.data_element3i;
8485         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8486         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8487         rsurface.modelelement3s = model->surfmesh.data_element3s;
8488         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8489         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8490         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8491         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8492         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8493         rsurface.modelsurfaces = model->data_surfaces;
8494         rsurface.batchgeneratedvertex = false;
8495         rsurface.batchfirstvertex = 0;
8496         rsurface.batchnumvertices = 0;
8497         rsurface.batchfirsttriangle = 0;
8498         rsurface.batchnumtriangles = 0;
8499         rsurface.batchvertex3f  = NULL;
8500         rsurface.batchvertex3f_vertexbuffer = NULL;
8501         rsurface.batchvertex3f_bufferoffset = 0;
8502         rsurface.batchsvector3f = NULL;
8503         rsurface.batchsvector3f_vertexbuffer = NULL;
8504         rsurface.batchsvector3f_bufferoffset = 0;
8505         rsurface.batchtvector3f = NULL;
8506         rsurface.batchtvector3f_vertexbuffer = NULL;
8507         rsurface.batchtvector3f_bufferoffset = 0;
8508         rsurface.batchnormal3f  = NULL;
8509         rsurface.batchnormal3f_vertexbuffer = NULL;
8510         rsurface.batchnormal3f_bufferoffset = 0;
8511         rsurface.batchlightmapcolor4f = NULL;
8512         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8513         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8514         rsurface.batchtexcoordtexture2f = NULL;
8515         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8516         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8517         rsurface.batchtexcoordlightmap2f = NULL;
8518         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8519         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8520         rsurface.batchskeletalindex4ub = NULL;
8521         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8522         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8523         rsurface.batchskeletalweight4ub = NULL;
8524         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8525         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8526         rsurface.batchvertexmesh = NULL;
8527         rsurface.batchvertexmeshbuffer = NULL;
8528         rsurface.batchvertex3fbuffer = NULL;
8529         rsurface.batchelement3i = NULL;
8530         rsurface.batchelement3i_indexbuffer = NULL;
8531         rsurface.batchelement3i_bufferoffset = 0;
8532         rsurface.batchelement3s = NULL;
8533         rsurface.batchelement3s_indexbuffer = NULL;
8534         rsurface.batchelement3s_bufferoffset = 0;
8535         rsurface.passcolor4f = NULL;
8536         rsurface.passcolor4f_vertexbuffer = NULL;
8537         rsurface.passcolor4f_bufferoffset = 0;
8538         rsurface.forcecurrenttextureupdate = false;
8539 }
8540
8541 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)
8542 {
8543         rsurface.entity = r_refdef.scene.worldentity;
8544         rsurface.skeleton = NULL;
8545         rsurface.ent_skinnum = 0;
8546         rsurface.ent_qwskin = -1;
8547         rsurface.ent_flags = entflags;
8548         rsurface.shadertime = r_refdef.scene.time - shadertime;
8549         rsurface.modelnumvertices = numvertices;
8550         rsurface.modelnumtriangles = numtriangles;
8551         rsurface.matrix = *matrix;
8552         rsurface.inversematrix = *inversematrix;
8553         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8554         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8555         R_EntityMatrix(&rsurface.matrix);
8556         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8557         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8558         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8559         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8560         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8561         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8562         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8563         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8564         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8565         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8566         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8567         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8568         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);
8569         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8570         rsurface.frameblend[0].lerp = 1;
8571         rsurface.ent_alttextures = false;
8572         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8573         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8574         rsurface.entityskeletaltransform3x4 = NULL;
8575         rsurface.entityskeletalnumtransforms = 0;
8576         if (wanttangents)
8577         {
8578                 rsurface.modelvertex3f = (float *)vertex3f;
8579                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8580                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8581                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8582         }
8583         else if (wantnormals)
8584         {
8585                 rsurface.modelvertex3f = (float *)vertex3f;
8586                 rsurface.modelsvector3f = NULL;
8587                 rsurface.modeltvector3f = NULL;
8588                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8589         }
8590         else
8591         {
8592                 rsurface.modelvertex3f = (float *)vertex3f;
8593                 rsurface.modelsvector3f = NULL;
8594                 rsurface.modeltvector3f = NULL;
8595                 rsurface.modelnormal3f = NULL;
8596         }
8597         rsurface.modelvertexmesh = NULL;
8598         rsurface.modelvertexmeshbuffer = NULL;
8599         rsurface.modelvertex3fbuffer = NULL;
8600         rsurface.modelvertex3f_vertexbuffer = 0;
8601         rsurface.modelvertex3f_bufferoffset = 0;
8602         rsurface.modelsvector3f_vertexbuffer = 0;
8603         rsurface.modelsvector3f_bufferoffset = 0;
8604         rsurface.modeltvector3f_vertexbuffer = 0;
8605         rsurface.modeltvector3f_bufferoffset = 0;
8606         rsurface.modelnormal3f_vertexbuffer = 0;
8607         rsurface.modelnormal3f_bufferoffset = 0;
8608         rsurface.modelgeneratedvertex = true;
8609         rsurface.modellightmapcolor4f  = (float *)color4f;
8610         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8611         rsurface.modellightmapcolor4f_bufferoffset = 0;
8612         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8613         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8614         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8615         rsurface.modeltexcoordlightmap2f  = NULL;
8616         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8617         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8618         rsurface.modelskeletalindex4ub = NULL;
8619         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8620         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8621         rsurface.modelskeletalweight4ub = NULL;
8622         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8623         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8624         rsurface.modelelement3i = (int *)element3i;
8625         rsurface.modelelement3i_indexbuffer = NULL;
8626         rsurface.modelelement3i_bufferoffset = 0;
8627         rsurface.modelelement3s = (unsigned short *)element3s;
8628         rsurface.modelelement3s_indexbuffer = NULL;
8629         rsurface.modelelement3s_bufferoffset = 0;
8630         rsurface.modellightmapoffsets = NULL;
8631         rsurface.modelsurfaces = NULL;
8632         rsurface.batchgeneratedvertex = false;
8633         rsurface.batchfirstvertex = 0;
8634         rsurface.batchnumvertices = 0;
8635         rsurface.batchfirsttriangle = 0;
8636         rsurface.batchnumtriangles = 0;
8637         rsurface.batchvertex3f  = NULL;
8638         rsurface.batchvertex3f_vertexbuffer = NULL;
8639         rsurface.batchvertex3f_bufferoffset = 0;
8640         rsurface.batchsvector3f = NULL;
8641         rsurface.batchsvector3f_vertexbuffer = NULL;
8642         rsurface.batchsvector3f_bufferoffset = 0;
8643         rsurface.batchtvector3f = NULL;
8644         rsurface.batchtvector3f_vertexbuffer = NULL;
8645         rsurface.batchtvector3f_bufferoffset = 0;
8646         rsurface.batchnormal3f  = NULL;
8647         rsurface.batchnormal3f_vertexbuffer = NULL;
8648         rsurface.batchnormal3f_bufferoffset = 0;
8649         rsurface.batchlightmapcolor4f = NULL;
8650         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8651         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8652         rsurface.batchtexcoordtexture2f = NULL;
8653         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8654         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8655         rsurface.batchtexcoordlightmap2f = NULL;
8656         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8657         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8658         rsurface.batchskeletalindex4ub = NULL;
8659         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8660         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8661         rsurface.batchskeletalweight4ub = NULL;
8662         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8663         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8664         rsurface.batchvertexmesh = NULL;
8665         rsurface.batchvertexmeshbuffer = NULL;
8666         rsurface.batchvertex3fbuffer = NULL;
8667         rsurface.batchelement3i = NULL;
8668         rsurface.batchelement3i_indexbuffer = NULL;
8669         rsurface.batchelement3i_bufferoffset = 0;
8670         rsurface.batchelement3s = NULL;
8671         rsurface.batchelement3s_indexbuffer = NULL;
8672         rsurface.batchelement3s_bufferoffset = 0;
8673         rsurface.passcolor4f = NULL;
8674         rsurface.passcolor4f_vertexbuffer = NULL;
8675         rsurface.passcolor4f_bufferoffset = 0;
8676         rsurface.forcecurrenttextureupdate = true;
8677
8678         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8679         {
8680                 if ((wantnormals || wanttangents) && !normal3f)
8681                 {
8682                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8683                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8684                 }
8685                 if (wanttangents && !svector3f)
8686                 {
8687                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8688                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8689                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8690                 }
8691         }
8692 }
8693
8694 float RSurf_FogPoint(const float *v)
8695 {
8696         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8697         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8698         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8699         float FogHeightFade = r_refdef.fogheightfade;
8700         float fogfrac;
8701         unsigned int fogmasktableindex;
8702         if (r_refdef.fogplaneviewabove)
8703                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8704         else
8705                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8706         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8707         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8708 }
8709
8710 float RSurf_FogVertex(const float *v)
8711 {
8712         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8713         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8714         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8715         float FogHeightFade = rsurface.fogheightfade;
8716         float fogfrac;
8717         unsigned int fogmasktableindex;
8718         if (r_refdef.fogplaneviewabove)
8719                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8720         else
8721                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8722         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8723         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8724 }
8725
8726 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8727 {
8728         int i;
8729         for (i = 0;i < numelements;i++)
8730                 outelement3i[i] = inelement3i[i] + adjust;
8731 }
8732
8733 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8734 extern cvar_t gl_vbo;
8735 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8736 {
8737         int deformindex;
8738         int firsttriangle;
8739         int numtriangles;
8740         int firstvertex;
8741         int endvertex;
8742         int numvertices;
8743         int surfacefirsttriangle;
8744         int surfacenumtriangles;
8745         int surfacefirstvertex;
8746         int surfaceendvertex;
8747         int surfacenumvertices;
8748         int batchnumvertices;
8749         int batchnumtriangles;
8750         int needsupdate;
8751         int i, j;
8752         qboolean gaps;
8753         qboolean dynamicvertex;
8754         float amplitude;
8755         float animpos;
8756         float scale;
8757         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8758         float waveparms[4];
8759         unsigned char *ub;
8760         q3shaderinfo_deform_t *deform;
8761         const msurface_t *surface, *firstsurface;
8762         r_vertexmesh_t *vertexmesh;
8763         if (!texturenumsurfaces)
8764                 return;
8765         // find vertex range of this surface batch
8766         gaps = false;
8767         firstsurface = texturesurfacelist[0];
8768         firsttriangle = firstsurface->num_firsttriangle;
8769         batchnumvertices = 0;
8770         batchnumtriangles = 0;
8771         firstvertex = endvertex = firstsurface->num_firstvertex;
8772         for (i = 0;i < texturenumsurfaces;i++)
8773         {
8774                 surface = texturesurfacelist[i];
8775                 if (surface != firstsurface + i)
8776                         gaps = true;
8777                 surfacefirstvertex = surface->num_firstvertex;
8778                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8779                 surfacenumvertices = surface->num_vertices;
8780                 surfacenumtriangles = surface->num_triangles;
8781                 if (firstvertex > surfacefirstvertex)
8782                         firstvertex = surfacefirstvertex;
8783                 if (endvertex < surfaceendvertex)
8784                         endvertex = surfaceendvertex;
8785                 batchnumvertices += surfacenumvertices;
8786                 batchnumtriangles += surfacenumtriangles;
8787         }
8788
8789         // we now know the vertex range used, and if there are any gaps in it
8790         rsurface.batchfirstvertex = firstvertex;
8791         rsurface.batchnumvertices = endvertex - firstvertex;
8792         rsurface.batchfirsttriangle = firsttriangle;
8793         rsurface.batchnumtriangles = batchnumtriangles;
8794
8795         // this variable holds flags for which properties have been updated that
8796         // may require regenerating vertexmesh array...
8797         needsupdate = 0;
8798
8799         // check if any dynamic vertex processing must occur
8800         dynamicvertex = false;
8801
8802         // a cvar to force the dynamic vertex path to be taken, for debugging
8803         if (r_batch_debugdynamicvertexpath.integer)
8804                 dynamicvertex = true;
8805
8806         // if there is a chance of animated vertex colors, it's a dynamic batch
8807         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8808         {
8809                 dynamicvertex = true;
8810                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8811         }
8812
8813         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8814         {
8815                 switch (deform->deform)
8816                 {
8817                 default:
8818                 case Q3DEFORM_PROJECTIONSHADOW:
8819                 case Q3DEFORM_TEXT0:
8820                 case Q3DEFORM_TEXT1:
8821                 case Q3DEFORM_TEXT2:
8822                 case Q3DEFORM_TEXT3:
8823                 case Q3DEFORM_TEXT4:
8824                 case Q3DEFORM_TEXT5:
8825                 case Q3DEFORM_TEXT6:
8826                 case Q3DEFORM_TEXT7:
8827                 case Q3DEFORM_NONE:
8828                         break;
8829                 case Q3DEFORM_AUTOSPRITE:
8830                         dynamicvertex = true;
8831                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8832                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8833                         break;
8834                 case Q3DEFORM_AUTOSPRITE2:
8835                         dynamicvertex = true;
8836                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8837                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8838                         break;
8839                 case Q3DEFORM_NORMAL:
8840                         dynamicvertex = true;
8841                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8842                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8843                         break;
8844                 case Q3DEFORM_WAVE:
8845                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8846                                 break; // if wavefunc is a nop, ignore this transform
8847                         dynamicvertex = true;
8848                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8849                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8850                         break;
8851                 case Q3DEFORM_BULGE:
8852                         dynamicvertex = true;
8853                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8854                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8855                         break;
8856                 case Q3DEFORM_MOVE:
8857                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8858                                 break; // if wavefunc is a nop, ignore this transform
8859                         dynamicvertex = true;
8860                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8861                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8862                         break;
8863                 }
8864         }
8865         switch(rsurface.texture->tcgen.tcgen)
8866         {
8867         default:
8868         case Q3TCGEN_TEXTURE:
8869                 break;
8870         case Q3TCGEN_LIGHTMAP:
8871                 dynamicvertex = true;
8872                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8873                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8874                 break;
8875         case Q3TCGEN_VECTOR:
8876                 dynamicvertex = true;
8877                 batchneed |= BATCHNEED_ARRAY_VERTEX;
8878                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8879                 break;
8880         case Q3TCGEN_ENVIRONMENT:
8881                 dynamicvertex = true;
8882                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8883                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8884                 break;
8885         }
8886         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8887         {
8888                 dynamicvertex = true;
8889                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8890                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8891         }
8892
8893         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8894         {
8895                 dynamicvertex = true;
8896                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8897         }
8898
8899         // when the model data has no vertex buffer (dynamic mesh), we need to
8900         // eliminate gaps
8901         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8902                 batchneed |= BATCHNEED_NOGAPS;
8903
8904         // the caller can specify BATCHNEED_NOGAPS to force a batch with
8905         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
8906         // we ensure this by treating the vertex batch as dynamic...
8907         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
8908                 dynamicvertex = true;
8909
8910         if (dynamicvertex)
8911         {
8912                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8913                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8914                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8915                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8916                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8917                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8918                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8919                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
8920         }
8921
8922         // if needsupdate, we have to do a dynamic vertex batch for sure
8923         if (needsupdate & batchneed)
8924                 dynamicvertex = true;
8925
8926         // see if we need to build vertexmesh from arrays
8927         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8928                 dynamicvertex = true;
8929
8930         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
8931         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
8932                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
8933
8934         rsurface.batchvertex3f = rsurface.modelvertex3f;
8935         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8936         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8937         rsurface.batchsvector3f = rsurface.modelsvector3f;
8938         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8939         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8940         rsurface.batchtvector3f = rsurface.modeltvector3f;
8941         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8942         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8943         rsurface.batchnormal3f = rsurface.modelnormal3f;
8944         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8945         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8946         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8947         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8948         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8949         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8950         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8951         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8952         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8953         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8954         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8955         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
8956         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
8957         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
8958         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
8959         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
8960         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
8961         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8962         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8963         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8964         rsurface.batchelement3i = rsurface.modelelement3i;
8965         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8966         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8967         rsurface.batchelement3s = rsurface.modelelement3s;
8968         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8969         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8970         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
8971         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
8972
8973         // if any dynamic vertex processing has to occur in software, we copy the
8974         // entire surface list together before processing to rebase the vertices
8975         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8976         //
8977         // if any gaps exist and we do not have a static vertex buffer, we have to
8978         // copy the surface list together to avoid wasting upload bandwidth on the
8979         // vertices in the gaps.
8980         //
8981         // if gaps exist and we have a static vertex buffer, we can choose whether
8982         // to combine the index buffer ranges into one dynamic index buffer or
8983         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
8984         //
8985         // in many cases the batch is reduced to one draw call.
8986
8987         rsurface.batchmultidraw = false;
8988         rsurface.batchmultidrawnumsurfaces = 0;
8989         rsurface.batchmultidrawsurfacelist = NULL;
8990
8991         if (!dynamicvertex)
8992         {
8993                 // static vertex data, just set pointers...
8994                 rsurface.batchgeneratedvertex = false;
8995                 // if there are gaps, we want to build a combined index buffer,
8996                 // otherwise use the original static buffer with an appropriate offset
8997                 if (gaps)
8998                 {
8999                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9000                         {
9001                                 rsurface.batchmultidraw = true;
9002                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9003                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9004                                 return;
9005                         }
9006                         // build a new triangle elements array for this batch
9007                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9008                         rsurface.batchfirsttriangle = 0;
9009                         numtriangles = 0;
9010                         for (i = 0;i < texturenumsurfaces;i++)
9011                         {
9012                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9013                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9014                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9015                                 numtriangles += surfacenumtriangles;
9016                         }
9017                         rsurface.batchelement3i_indexbuffer = NULL;
9018                         rsurface.batchelement3i_bufferoffset = 0;
9019                         rsurface.batchelement3s = NULL;
9020                         rsurface.batchelement3s_indexbuffer = NULL;
9021                         rsurface.batchelement3s_bufferoffset = 0;
9022                         if (endvertex <= 65536)
9023                         {
9024                                 // make a 16bit (unsigned short) index array if possible
9025                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9026                                 for (i = 0;i < numtriangles*3;i++)
9027                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9028                         }
9029                 }
9030                 return;
9031         }
9032
9033         // something needs software processing, do it for real...
9034         // we only directly handle separate array data in this case and then
9035         // generate interleaved data if needed...
9036         rsurface.batchgeneratedvertex = true;
9037
9038         // now copy the vertex data into a combined array and make an index array
9039         // (this is what Quake3 does all the time)
9040         // we also apply any skeletal animation here that would have been done in
9041         // the vertex shader, because most of the dynamic vertex animation cases
9042         // need actual vertex positions and normals
9043         //if (dynamicvertex)
9044         {
9045                 rsurface.batchvertex3fbuffer = NULL;
9046                 rsurface.batchvertexmesh = NULL;
9047                 rsurface.batchvertexmeshbuffer = NULL;
9048                 rsurface.batchvertex3f = NULL;
9049                 rsurface.batchvertex3f_vertexbuffer = NULL;
9050                 rsurface.batchvertex3f_bufferoffset = 0;
9051                 rsurface.batchsvector3f = NULL;
9052                 rsurface.batchsvector3f_vertexbuffer = NULL;
9053                 rsurface.batchsvector3f_bufferoffset = 0;
9054                 rsurface.batchtvector3f = NULL;
9055                 rsurface.batchtvector3f_vertexbuffer = NULL;
9056                 rsurface.batchtvector3f_bufferoffset = 0;
9057                 rsurface.batchnormal3f = NULL;
9058                 rsurface.batchnormal3f_vertexbuffer = NULL;
9059                 rsurface.batchnormal3f_bufferoffset = 0;
9060                 rsurface.batchlightmapcolor4f = NULL;
9061                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9062                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9063                 rsurface.batchtexcoordtexture2f = NULL;
9064                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9065                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9066                 rsurface.batchtexcoordlightmap2f = NULL;
9067                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9068                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9069                 rsurface.batchskeletalindex4ub = NULL;
9070                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9071                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9072                 rsurface.batchskeletalweight4ub = NULL;
9073                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9074                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9075                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9076                 rsurface.batchelement3i_indexbuffer = NULL;
9077                 rsurface.batchelement3i_bufferoffset = 0;
9078                 rsurface.batchelement3s = NULL;
9079                 rsurface.batchelement3s_indexbuffer = NULL;
9080                 rsurface.batchelement3s_bufferoffset = 0;
9081                 // we'll only be setting up certain arrays as needed
9082                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9083                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9084                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9085                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9086                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9087                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9088                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9089                 {
9090                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9091                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9092                 }
9093                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9094                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9095                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9096                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9097                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9098                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9099                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9100                 {
9101                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9102                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9103                 }
9104                 numvertices = 0;
9105                 numtriangles = 0;
9106                 for (i = 0;i < texturenumsurfaces;i++)
9107                 {
9108                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9109                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9110                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9111                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9112                         // copy only the data requested
9113                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9114                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9115                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9116                         {
9117                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9118                                 {
9119                                         if (rsurface.batchvertex3f)
9120                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9121                                         else
9122                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9123                                 }
9124                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9125                                 {
9126                                         if (rsurface.modelnormal3f)
9127                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9128                                         else
9129                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9130                                 }
9131                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9132                                 {
9133                                         if (rsurface.modelsvector3f)
9134                                         {
9135                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9136                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9137                                         }
9138                                         else
9139                                         {
9140                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9141                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9142                                         }
9143                                 }
9144                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9145                                 {
9146                                         if (rsurface.modellightmapcolor4f)
9147                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9148                                         else
9149                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9150                                 }
9151                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9152                                 {
9153                                         if (rsurface.modeltexcoordtexture2f)
9154                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9155                                         else
9156                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9157                                 }
9158                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9159                                 {
9160                                         if (rsurface.modeltexcoordlightmap2f)
9161                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9162                                         else
9163                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9164                                 }
9165                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9166                                 {
9167                                         if (rsurface.modelskeletalindex4ub)
9168                                         {
9169                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9170                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9171                                         }
9172                                         else
9173                                         {
9174                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9175                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9176                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9177                                                 for (j = 0;j < surfacenumvertices;j++)
9178                                                         ub[j*4] = 255;
9179                                         }
9180                                 }
9181                         }
9182                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9183                         numvertices += surfacenumvertices;
9184                         numtriangles += surfacenumtriangles;
9185                 }
9186
9187                 // generate a 16bit index array as well if possible
9188                 // (in general, dynamic batches fit)
9189                 if (numvertices <= 65536)
9190                 {
9191                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9192                         for (i = 0;i < numtriangles*3;i++)
9193                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9194                 }
9195
9196                 // since we've copied everything, the batch now starts at 0
9197                 rsurface.batchfirstvertex = 0;
9198                 rsurface.batchnumvertices = batchnumvertices;
9199                 rsurface.batchfirsttriangle = 0;
9200                 rsurface.batchnumtriangles = batchnumtriangles;
9201         }
9202
9203         // apply skeletal animation that would have been done in the vertex shader
9204         if (rsurface.batchskeletaltransform3x4)
9205         {
9206                 const unsigned char *si;
9207                 const unsigned char *sw;
9208                 const float *t[4];
9209                 const float *b = rsurface.batchskeletaltransform3x4;
9210                 float *vp, *vs, *vt, *vn;
9211                 float w[4];
9212                 float m[3][4], n[3][4];
9213                 float tp[3], ts[3], tt[3], tn[3];
9214                 si = rsurface.batchskeletalindex4ub;
9215                 sw = rsurface.batchskeletalweight4ub;
9216                 vp = rsurface.batchvertex3f;
9217                 vs = rsurface.batchsvector3f;
9218                 vt = rsurface.batchtvector3f;
9219                 vn = rsurface.batchnormal3f;
9220                 memset(m[0], 0, sizeof(m));
9221                 memset(n[0], 0, sizeof(n));
9222                 for (i = 0;i < batchnumvertices;i++)
9223                 {
9224                         t[0] = b + si[0]*12;
9225                         if (sw[0] == 255)
9226                         {
9227                                 // common case - only one matrix
9228                                 m[0][0] = t[0][ 0];
9229                                 m[0][1] = t[0][ 1];
9230                                 m[0][2] = t[0][ 2];
9231                                 m[0][3] = t[0][ 3];
9232                                 m[1][0] = t[0][ 4];
9233                                 m[1][1] = t[0][ 5];
9234                                 m[1][2] = t[0][ 6];
9235                                 m[1][3] = t[0][ 7];
9236                                 m[2][0] = t[0][ 8];
9237                                 m[2][1] = t[0][ 9];
9238                                 m[2][2] = t[0][10];
9239                                 m[2][3] = t[0][11];
9240                         }
9241                         else if (sw[2] + sw[3])
9242                         {
9243                                 // blend 4 matrices
9244                                 t[1] = b + si[1]*12;
9245                                 t[2] = b + si[2]*12;
9246                                 t[3] = b + si[3]*12;
9247                                 w[0] = sw[0] * (1.0f / 255.0f);
9248                                 w[1] = sw[1] * (1.0f / 255.0f);
9249                                 w[2] = sw[2] * (1.0f / 255.0f);
9250                                 w[3] = sw[3] * (1.0f / 255.0f);
9251                                 // blend the matrices
9252                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9253                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9254                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9255                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9256                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9257                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9258                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9259                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9260                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9261                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9262                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9263                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9264                         }
9265                         else
9266                         {
9267                                 // blend 2 matrices
9268                                 t[1] = b + si[1]*12;
9269                                 w[0] = sw[0] * (1.0f / 255.0f);
9270                                 w[1] = sw[1] * (1.0f / 255.0f);
9271                                 // blend the matrices
9272                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9273                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9274                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9275                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9276                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9277                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9278                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9279                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9280                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9281                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9282                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9283                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9284                         }
9285                         si += 4;
9286                         sw += 4;
9287                         // modify the vertex
9288                         VectorCopy(vp, tp);
9289                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9290                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9291                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9292                         vp += 3;
9293                         if (vn)
9294                         {
9295                                 // the normal transformation matrix is a set of cross products...
9296                                 CrossProduct(m[1], m[2], n[0]);
9297                                 CrossProduct(m[2], m[0], n[1]);
9298                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9299                                 VectorCopy(vn, tn);
9300                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9301                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9302                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9303                                 VectorNormalize(vn);
9304                                 vn += 3;
9305                                 if (vs)
9306                                 {
9307                                         VectorCopy(vs, ts);
9308                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9309                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9310                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9311                                         VectorNormalize(vs);
9312                                         vs += 3;
9313                                         VectorCopy(vt, tt);
9314                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9315                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9316                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9317                                         VectorNormalize(vt);
9318                                         vt += 3;
9319                                 }
9320                         }
9321                 }
9322                 rsurface.batchskeletaltransform3x4 = NULL;
9323                 rsurface.batchskeletalnumtransforms = 0;
9324         }
9325
9326         // q1bsp surfaces rendered in vertex color mode have to have colors
9327         // calculated based on lightstyles
9328         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9329         {
9330                 // generate color arrays for the surfaces in this list
9331                 int c[4];
9332                 int scale;
9333                 int size3;
9334                 const int *offsets;
9335                 const unsigned char *lm;
9336                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9337                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9338                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9339                 numvertices = 0;
9340                 for (i = 0;i < texturenumsurfaces;i++)
9341                 {
9342                         surface = texturesurfacelist[i];
9343                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9344                         surfacenumvertices = surface->num_vertices;
9345                         if (surface->lightmapinfo->samples)
9346                         {
9347                                 for (j = 0;j < surfacenumvertices;j++)
9348                                 {
9349                                         lm = surface->lightmapinfo->samples + offsets[j];
9350                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9351                                         VectorScale(lm, scale, c);
9352                                         if (surface->lightmapinfo->styles[1] != 255)
9353                                         {
9354                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9355                                                 lm += size3;
9356                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9357                                                 VectorMA(c, scale, lm, c);
9358                                                 if (surface->lightmapinfo->styles[2] != 255)
9359                                                 {
9360                                                         lm += size3;
9361                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9362                                                         VectorMA(c, scale, lm, c);
9363                                                         if (surface->lightmapinfo->styles[3] != 255)
9364                                                         {
9365                                                                 lm += size3;
9366                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9367                                                                 VectorMA(c, scale, lm, c);
9368                                                         }
9369                                                 }
9370                                         }
9371                                         c[0] >>= 7;
9372                                         c[1] >>= 7;
9373                                         c[2] >>= 7;
9374                                         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);
9375                                         numvertices++;
9376                                 }
9377                         }
9378                         else
9379                         {
9380                                 for (j = 0;j < surfacenumvertices;j++)
9381                                 {
9382                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9383                                         numvertices++;
9384                                 }
9385                         }
9386                 }
9387         }
9388
9389         // if vertices are deformed (sprite flares and things in maps, possibly
9390         // water waves, bulges and other deformations), modify the copied vertices
9391         // in place
9392         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9393         {
9394                 switch (deform->deform)
9395                 {
9396                 default:
9397                 case Q3DEFORM_PROJECTIONSHADOW:
9398                 case Q3DEFORM_TEXT0:
9399                 case Q3DEFORM_TEXT1:
9400                 case Q3DEFORM_TEXT2:
9401                 case Q3DEFORM_TEXT3:
9402                 case Q3DEFORM_TEXT4:
9403                 case Q3DEFORM_TEXT5:
9404                 case Q3DEFORM_TEXT6:
9405                 case Q3DEFORM_TEXT7:
9406                 case Q3DEFORM_NONE:
9407                         break;
9408                 case Q3DEFORM_AUTOSPRITE:
9409                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9410                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9411                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9412                         VectorNormalize(newforward);
9413                         VectorNormalize(newright);
9414                         VectorNormalize(newup);
9415 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9416 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9417 //                      rsurface.batchvertex3f_bufferoffset = 0;
9418 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9419 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9420 //                      rsurface.batchsvector3f_bufferoffset = 0;
9421 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9422 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9423 //                      rsurface.batchtvector3f_bufferoffset = 0;
9424 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9425 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9426 //                      rsurface.batchnormal3f_bufferoffset = 0;
9427                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9428                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9429                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9430                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9431                                 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);
9432                         // a single autosprite surface can contain multiple sprites...
9433                         for (j = 0;j < batchnumvertices - 3;j += 4)
9434                         {
9435                                 VectorClear(center);
9436                                 for (i = 0;i < 4;i++)
9437                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9438                                 VectorScale(center, 0.25f, center);
9439                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9440                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9441                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9442                                 for (i = 0;i < 4;i++)
9443                                 {
9444                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9445                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9446                                 }
9447                         }
9448                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9449                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9450                         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);
9451                         break;
9452                 case Q3DEFORM_AUTOSPRITE2:
9453                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9454                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9455                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9456                         VectorNormalize(newforward);
9457                         VectorNormalize(newright);
9458                         VectorNormalize(newup);
9459 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9460 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9461 //                      rsurface.batchvertex3f_bufferoffset = 0;
9462                         {
9463                                 const float *v1, *v2;
9464                                 vec3_t start, end;
9465                                 float f, l;
9466                                 struct
9467                                 {
9468                                         float length2;
9469                                         const float *v1;
9470                                         const float *v2;
9471                                 }
9472                                 shortest[2];
9473                                 memset(shortest, 0, sizeof(shortest));
9474                                 // a single autosprite surface can contain multiple sprites...
9475                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9476                                 {
9477                                         VectorClear(center);
9478                                         for (i = 0;i < 4;i++)
9479                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9480                                         VectorScale(center, 0.25f, center);
9481                                         // find the two shortest edges, then use them to define the
9482                                         // axis vectors for rotating around the central axis
9483                                         for (i = 0;i < 6;i++)
9484                                         {
9485                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9486                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9487                                                 l = VectorDistance2(v1, v2);
9488                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9489                                                 if (v1[2] != v2[2])
9490                                                         l += (1.0f / 1024.0f);
9491                                                 if (shortest[0].length2 > l || i == 0)
9492                                                 {
9493                                                         shortest[1] = shortest[0];
9494                                                         shortest[0].length2 = l;
9495                                                         shortest[0].v1 = v1;
9496                                                         shortest[0].v2 = v2;
9497                                                 }
9498                                                 else if (shortest[1].length2 > l || i == 1)
9499                                                 {
9500                                                         shortest[1].length2 = l;
9501                                                         shortest[1].v1 = v1;
9502                                                         shortest[1].v2 = v2;
9503                                                 }
9504                                         }
9505                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9506                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9507                                         // this calculates the right vector from the shortest edge
9508                                         // and the up vector from the edge midpoints
9509                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9510                                         VectorNormalize(right);
9511                                         VectorSubtract(end, start, up);
9512                                         VectorNormalize(up);
9513                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9514                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9515                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9516                                         VectorNegate(forward, forward);
9517                                         VectorReflect(forward, 0, up, forward);
9518                                         VectorNormalize(forward);
9519                                         CrossProduct(up, forward, newright);
9520                                         VectorNormalize(newright);
9521                                         // rotate the quad around the up axis vector, this is made
9522                                         // especially easy by the fact we know the quad is flat,
9523                                         // so we only have to subtract the center position and
9524                                         // measure distance along the right vector, and then
9525                                         // multiply that by the newright vector and add back the
9526                                         // center position
9527                                         // we also need to subtract the old position to undo the
9528                                         // displacement from the center, which we do with a
9529                                         // DotProduct, the subtraction/addition of center is also
9530                                         // optimized into DotProducts here
9531                                         l = DotProduct(right, center);
9532                                         for (i = 0;i < 4;i++)
9533                                         {
9534                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9535                                                 f = DotProduct(right, v1) - l;
9536                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9537                                         }
9538                                 }
9539                         }
9540                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9541                         {
9542 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9543 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9544 //                              rsurface.batchnormal3f_bufferoffset = 0;
9545                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9546                         }
9547                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9548                         {
9549 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9550 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9551 //                              rsurface.batchsvector3f_bufferoffset = 0;
9552 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9553 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9554 //                              rsurface.batchtvector3f_bufferoffset = 0;
9555                                 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);
9556                         }
9557                         break;
9558                 case Q3DEFORM_NORMAL:
9559                         // deform the normals to make reflections wavey
9560                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9561                         rsurface.batchnormal3f_vertexbuffer = NULL;
9562                         rsurface.batchnormal3f_bufferoffset = 0;
9563                         for (j = 0;j < batchnumvertices;j++)
9564                         {
9565                                 float vertex[3];
9566                                 float *normal = rsurface.batchnormal3f + 3*j;
9567                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9568                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9569                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9570                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9571                                 VectorNormalize(normal);
9572                         }
9573                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9574                         {
9575 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9576 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9577 //                              rsurface.batchsvector3f_bufferoffset = 0;
9578 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9579 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9580 //                              rsurface.batchtvector3f_bufferoffset = 0;
9581                                 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);
9582                         }
9583                         break;
9584                 case Q3DEFORM_WAVE:
9585                         // deform vertex array to make wavey water and flags and such
9586                         waveparms[0] = deform->waveparms[0];
9587                         waveparms[1] = deform->waveparms[1];
9588                         waveparms[2] = deform->waveparms[2];
9589                         waveparms[3] = deform->waveparms[3];
9590                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9591                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9592                         // this is how a divisor of vertex influence on deformation
9593                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9594                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9595 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9596 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9597 //                      rsurface.batchvertex3f_bufferoffset = 0;
9598 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9599 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9600 //                      rsurface.batchnormal3f_bufferoffset = 0;
9601                         for (j = 0;j < batchnumvertices;j++)
9602                         {
9603                                 // if the wavefunc depends on time, evaluate it per-vertex
9604                                 if (waveparms[3])
9605                                 {
9606                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9607                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9608                                 }
9609                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9610                         }
9611                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9612                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9613                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9614                         {
9615 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9616 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9617 //                              rsurface.batchsvector3f_bufferoffset = 0;
9618 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9619 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9620 //                              rsurface.batchtvector3f_bufferoffset = 0;
9621                                 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);
9622                         }
9623                         break;
9624                 case Q3DEFORM_BULGE:
9625                         // deform vertex array to make the surface have moving bulges
9626 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9627 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9628 //                      rsurface.batchvertex3f_bufferoffset = 0;
9629 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9630 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9631 //                      rsurface.batchnormal3f_bufferoffset = 0;
9632                         for (j = 0;j < batchnumvertices;j++)
9633                         {
9634                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9635                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9636                         }
9637                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9638                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9639                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9640                         {
9641 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9642 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9643 //                              rsurface.batchsvector3f_bufferoffset = 0;
9644 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9645 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9646 //                              rsurface.batchtvector3f_bufferoffset = 0;
9647                                 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);
9648                         }
9649                         break;
9650                 case Q3DEFORM_MOVE:
9651                         // deform vertex array
9652                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9653                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9654                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9655                         VectorScale(deform->parms, scale, waveparms);
9656 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9657 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9658 //                      rsurface.batchvertex3f_bufferoffset = 0;
9659                         for (j = 0;j < batchnumvertices;j++)
9660                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9661                         break;
9662                 }
9663         }
9664
9665         // generate texcoords based on the chosen texcoord source
9666         switch(rsurface.texture->tcgen.tcgen)
9667         {
9668         default:
9669         case Q3TCGEN_TEXTURE:
9670                 break;
9671         case Q3TCGEN_LIGHTMAP:
9672 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9673 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9674 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9675                 if (rsurface.batchtexcoordlightmap2f)
9676                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9677                 break;
9678         case Q3TCGEN_VECTOR:
9679 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9680 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9681 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9682                 for (j = 0;j < batchnumvertices;j++)
9683                 {
9684                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9685                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9686                 }
9687                 break;
9688         case Q3TCGEN_ENVIRONMENT:
9689                 // make environment reflections using a spheremap
9690                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9691                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9692                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9693                 for (j = 0;j < batchnumvertices;j++)
9694                 {
9695                         // identical to Q3A's method, but executed in worldspace so
9696                         // carried models can be shiny too
9697
9698                         float viewer[3], d, reflected[3], worldreflected[3];
9699
9700                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9701                         // VectorNormalize(viewer);
9702
9703                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9704
9705                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9706                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9707                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9708                         // note: this is proportinal to viewer, so we can normalize later
9709
9710                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9711                         VectorNormalize(worldreflected);
9712
9713                         // note: this sphere map only uses world x and z!
9714                         // so positive and negative y will LOOK THE SAME.
9715                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9716                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9717                 }
9718                 break;
9719         }
9720         // the only tcmod that needs software vertex processing is turbulent, so
9721         // check for it here and apply the changes if needed
9722         // and we only support that as the first one
9723         // (handling a mixture of turbulent and other tcmods would be problematic
9724         //  without punting it entirely to a software path)
9725         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9726         {
9727                 amplitude = rsurface.texture->tcmods[0].parms[1];
9728                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9729 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9730 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9731 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9732                 for (j = 0;j < batchnumvertices;j++)
9733                 {
9734                         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);
9735                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9736                 }
9737         }
9738
9739         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9740         {
9741                 // convert the modified arrays to vertex structs
9742 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9743 //              rsurface.batchvertexmeshbuffer = NULL;
9744                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9745                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9746                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9747                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9748                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9749                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9750                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9751                 {
9752                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9753                         {
9754                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9755                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9756                         }
9757                 }
9758                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9759                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9760                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9761                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9762                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9763                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9764                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9765                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9766                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9767                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9768                 {
9769                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9770                         {
9771                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9772                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9773                         }
9774                 }
9775         }
9776 }
9777
9778 void RSurf_DrawBatch(void)
9779 {
9780         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9781         // through the pipeline, killing it earlier in the pipeline would have
9782         // per-surface overhead rather than per-batch overhead, so it's best to
9783         // reject it here, before it hits glDraw.
9784         if (rsurface.batchnumtriangles == 0)
9785                 return;
9786 #if 0
9787         // batch debugging code
9788         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9789         {
9790                 int i;
9791                 int j;
9792                 int c;
9793                 const int *e;
9794                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9795                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9796                 {
9797                         c = e[i];
9798                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9799                         {
9800                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9801                                 {
9802                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9803                                                 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);
9804                                         break;
9805                                 }
9806                         }
9807                 }
9808         }
9809 #endif
9810         if (rsurface.batchmultidraw)
9811         {
9812                 // issue multiple draws rather than copying index data
9813                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9814                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9815                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9816                 for (i = 0;i < numsurfaces;)
9817                 {
9818                         // combine consecutive surfaces as one draw
9819                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9820                                 if (surfacelist[j] != surfacelist[k] + 1)
9821                                         break;
9822                         firstvertex = surfacelist[i]->num_firstvertex;
9823                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9824                         firsttriangle = surfacelist[i]->num_firsttriangle;
9825                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9826                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
9827                         i = j;
9828                 }
9829         }
9830         else
9831         {
9832                 // there is only one consecutive run of index data (may have been combined)
9833                 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);
9834         }
9835 }
9836
9837 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9838 {
9839         // pick the closest matching water plane
9840         int planeindex, vertexindex, bestplaneindex = -1;
9841         float d, bestd;
9842         vec3_t vert;
9843         const float *v;
9844         r_waterstate_waterplane_t *p;
9845         qboolean prepared = false;
9846         bestd = 0;
9847         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9848         {
9849                 if(p->camera_entity != rsurface.texture->camera_entity)
9850                         continue;
9851                 d = 0;
9852                 if(!prepared)
9853                 {
9854                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
9855                         prepared = true;
9856                         if(rsurface.batchnumvertices == 0)
9857                                 break;
9858                 }
9859                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9860                 {
9861                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9862                         d += fabs(PlaneDiff(vert, &p->plane));
9863                 }
9864                 if (bestd > d || bestplaneindex < 0)
9865                 {
9866                         bestd = d;
9867                         bestplaneindex = planeindex;
9868                 }
9869         }
9870         return bestplaneindex;
9871         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9872         // this situation though, as it might be better to render single larger
9873         // batches with useless stuff (backface culled for example) than to
9874         // render multiple smaller batches
9875 }
9876
9877 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9878 {
9879         int i;
9880         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9881         rsurface.passcolor4f_vertexbuffer = 0;
9882         rsurface.passcolor4f_bufferoffset = 0;
9883         for (i = 0;i < rsurface.batchnumvertices;i++)
9884                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9885 }
9886
9887 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9888 {
9889         int i;
9890         float f;
9891         const float *v;
9892         const float *c;
9893         float *c2;
9894         if (rsurface.passcolor4f)
9895         {
9896                 // generate color arrays
9897                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9898                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9899                 rsurface.passcolor4f_vertexbuffer = 0;
9900                 rsurface.passcolor4f_bufferoffset = 0;
9901                 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)
9902                 {
9903                         f = RSurf_FogVertex(v);
9904                         c2[0] = c[0] * f;
9905                         c2[1] = c[1] * f;
9906                         c2[2] = c[2] * f;
9907                         c2[3] = c[3];
9908                 }
9909         }
9910         else
9911         {
9912                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9913                 rsurface.passcolor4f_vertexbuffer = 0;
9914                 rsurface.passcolor4f_bufferoffset = 0;
9915                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9916                 {
9917                         f = RSurf_FogVertex(v);
9918                         c2[0] = f;
9919                         c2[1] = f;
9920                         c2[2] = f;
9921                         c2[3] = 1;
9922                 }
9923         }
9924 }
9925
9926 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9927 {
9928         int i;
9929         float f;
9930         const float *v;
9931         const float *c;
9932         float *c2;
9933         if (!rsurface.passcolor4f)
9934                 return;
9935         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9936         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9937         rsurface.passcolor4f_vertexbuffer = 0;
9938         rsurface.passcolor4f_bufferoffset = 0;
9939         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)
9940         {
9941                 f = RSurf_FogVertex(v);
9942                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9943                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9944                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9945                 c2[3] = c[3];
9946         }
9947 }
9948
9949 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9950 {
9951         int i;
9952         const float *c;
9953         float *c2;
9954         if (!rsurface.passcolor4f)
9955                 return;
9956         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9957         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9958         rsurface.passcolor4f_vertexbuffer = 0;
9959         rsurface.passcolor4f_bufferoffset = 0;
9960         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9961         {
9962                 c2[0] = c[0] * r;
9963                 c2[1] = c[1] * g;
9964                 c2[2] = c[2] * b;
9965                 c2[3] = c[3] * a;
9966         }
9967 }
9968
9969 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9970 {
9971         int i;
9972         const float *c;
9973         float *c2;
9974         if (!rsurface.passcolor4f)
9975                 return;
9976         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9977         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9978         rsurface.passcolor4f_vertexbuffer = 0;
9979         rsurface.passcolor4f_bufferoffset = 0;
9980         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9981         {
9982                 c2[0] = c[0] + r_refdef.scene.ambient;
9983                 c2[1] = c[1] + r_refdef.scene.ambient;
9984                 c2[2] = c[2] + r_refdef.scene.ambient;
9985                 c2[3] = c[3];
9986         }
9987 }
9988
9989 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9990 {
9991         // TODO: optimize
9992         rsurface.passcolor4f = NULL;
9993         rsurface.passcolor4f_vertexbuffer = 0;
9994         rsurface.passcolor4f_bufferoffset = 0;
9995         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9996         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9997         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9998         GL_Color(r, g, b, a);
9999         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10000         RSurf_DrawBatch();
10001 }
10002
10003 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10004 {
10005         // TODO: optimize applyfog && applycolor case
10006         // just apply fog if necessary, and tint the fog color array if necessary
10007         rsurface.passcolor4f = NULL;
10008         rsurface.passcolor4f_vertexbuffer = 0;
10009         rsurface.passcolor4f_bufferoffset = 0;
10010         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10011         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10012         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10013         GL_Color(r, g, b, a);
10014         RSurf_DrawBatch();
10015 }
10016
10017 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10018 {
10019         // TODO: optimize
10020         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10021         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10022         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10023         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10024         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10025         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10026         GL_Color(r, g, b, a);
10027         RSurf_DrawBatch();
10028 }
10029
10030 static void RSurf_DrawBatch_GL11_ClampColor(void)
10031 {
10032         int i;
10033         const float *c1;
10034         float *c2;
10035         if (!rsurface.passcolor4f)
10036                 return;
10037         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10038         {
10039                 c2[0] = bound(0.0f, c1[0], 1.0f);
10040                 c2[1] = bound(0.0f, c1[1], 1.0f);
10041                 c2[2] = bound(0.0f, c1[2], 1.0f);
10042                 c2[3] = bound(0.0f, c1[3], 1.0f);
10043         }
10044 }
10045
10046 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10047 {
10048         int i;
10049         float f;
10050         const float *v;
10051         const float *n;
10052         float *c;
10053         //vec3_t eyedir;
10054
10055         // fake shading
10056         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10057         rsurface.passcolor4f_vertexbuffer = 0;
10058         rsurface.passcolor4f_bufferoffset = 0;
10059         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)
10060         {
10061                 f = -DotProduct(r_refdef.view.forward, n);
10062                 f = max(0, f);
10063                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10064                 f *= r_refdef.lightmapintensity;
10065                 Vector4Set(c, f, f, f, 1);
10066         }
10067 }
10068
10069 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10070 {
10071         RSurf_DrawBatch_GL11_ApplyFakeLight();
10072         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10073         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10074         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10075         GL_Color(r, g, b, a);
10076         RSurf_DrawBatch();
10077 }
10078
10079 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10080 {
10081         int i;
10082         float f;
10083         float alpha;
10084         const float *v;
10085         const float *n;
10086         float *c;
10087         vec3_t ambientcolor;
10088         vec3_t diffusecolor;
10089         vec3_t lightdir;
10090         // TODO: optimize
10091         // model lighting
10092         VectorCopy(rsurface.modellight_lightdir, lightdir);
10093         f = 0.5f * r_refdef.lightmapintensity;
10094         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10095         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10096         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10097         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10098         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10099         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10100         alpha = *a;
10101         if (VectorLength2(diffusecolor) > 0)
10102         {
10103                 // q3-style directional shading
10104                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10105                 rsurface.passcolor4f_vertexbuffer = 0;
10106                 rsurface.passcolor4f_bufferoffset = 0;
10107                 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)
10108                 {
10109                         if ((f = DotProduct(n, lightdir)) > 0)
10110                                 VectorMA(ambientcolor, f, diffusecolor, c);
10111                         else
10112                                 VectorCopy(ambientcolor, c);
10113                         c[3] = alpha;
10114                 }
10115                 *r = 1;
10116                 *g = 1;
10117                 *b = 1;
10118                 *a = 1;
10119                 *applycolor = false;
10120         }
10121         else
10122         {
10123                 *r = ambientcolor[0];
10124                 *g = ambientcolor[1];
10125                 *b = ambientcolor[2];
10126                 rsurface.passcolor4f = NULL;
10127                 rsurface.passcolor4f_vertexbuffer = 0;
10128                 rsurface.passcolor4f_bufferoffset = 0;
10129         }
10130 }
10131
10132 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10133 {
10134         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10135         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10136         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10137         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10138         GL_Color(r, g, b, a);
10139         RSurf_DrawBatch();
10140 }
10141
10142 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10143 {
10144         int i;
10145         float f;
10146         const float *v;
10147         float *c;
10148
10149         // fake shading
10150         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10151         rsurface.passcolor4f_vertexbuffer = 0;
10152         rsurface.passcolor4f_bufferoffset = 0;
10153
10154         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10155         {
10156                 f = 1 - RSurf_FogVertex(v);
10157                 c[0] = r;
10158                 c[1] = g;
10159                 c[2] = b;
10160                 c[3] = f * a;
10161         }
10162 }
10163
10164 void RSurf_SetupDepthAndCulling(void)
10165 {
10166         // submodels are biased to avoid z-fighting with world surfaces that they
10167         // may be exactly overlapping (avoids z-fighting artifacts on certain
10168         // doors and things in Quake maps)
10169         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10170         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10171         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10172         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10173 }
10174
10175 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10176 {
10177         // transparent sky would be ridiculous
10178         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10179                 return;
10180         R_SetupShader_Generic_NoTexture(false, false);
10181         skyrenderlater = true;
10182         RSurf_SetupDepthAndCulling();
10183         GL_DepthMask(true);
10184         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10185         // skymasking on them, and Quake3 never did sky masking (unlike
10186         // software Quake and software Quake2), so disable the sky masking
10187         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10188         // and skymasking also looks very bad when noclipping outside the
10189         // level, so don't use it then either.
10190         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10191         {
10192                 R_Mesh_ResetTextureState();
10193                 if (skyrendermasked)
10194                 {
10195                         R_SetupShader_DepthOrShadow(false, false);
10196                         // depth-only (masking)
10197                         GL_ColorMask(0,0,0,0);
10198                         // just to make sure that braindead drivers don't draw
10199                         // anything despite that colormask...
10200                         GL_BlendFunc(GL_ZERO, GL_ONE);
10201                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10202                         if (rsurface.batchvertex3fbuffer)
10203                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10204                         else
10205                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10206                 }
10207                 else
10208                 {
10209                         R_SetupShader_Generic_NoTexture(false, false);
10210                         // fog sky
10211                         GL_BlendFunc(GL_ONE, GL_ZERO);
10212                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10213                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10214                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10215                 }
10216                 RSurf_DrawBatch();
10217                 if (skyrendermasked)
10218                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10219         }
10220         R_Mesh_ResetTextureState();
10221         GL_Color(1, 1, 1, 1);
10222 }
10223
10224 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10225 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10226 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10227 {
10228         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10229                 return;
10230         if (prepass)
10231         {
10232                 // render screenspace normalmap to texture
10233                 GL_DepthMask(true);
10234                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10235                 RSurf_DrawBatch();
10236                 return;
10237         }
10238
10239         // bind lightmap texture
10240
10241         // water/refraction/reflection/camera surfaces have to be handled specially
10242         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10243         {
10244                 int start, end, startplaneindex;
10245                 for (start = 0;start < texturenumsurfaces;start = end)
10246                 {
10247                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10248                         if(startplaneindex < 0)
10249                         {
10250                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10251                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10252                                 end = start + 1;
10253                                 continue;
10254                         }
10255                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10256                                 ;
10257                         // now that we have a batch using the same planeindex, render it
10258                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10259                         {
10260                                 // render water or distortion background
10261                                 GL_DepthMask(true);
10262                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10263                                 RSurf_DrawBatch();
10264                                 // blend surface on top
10265                                 GL_DepthMask(false);
10266                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10267                                 RSurf_DrawBatch();
10268                         }
10269                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10270                         {
10271                                 // render surface with reflection texture as input
10272                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10273                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10274                                 RSurf_DrawBatch();
10275                         }
10276                 }
10277                 return;
10278         }
10279
10280         // render surface batch normally
10281         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10282         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);
10283         RSurf_DrawBatch();
10284 }
10285
10286 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10287 {
10288         // OpenGL 1.3 path - anything not completely ancient
10289         qboolean applycolor;
10290         qboolean applyfog;
10291         int layerindex;
10292         const texturelayer_t *layer;
10293         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);
10294         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10295
10296         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10297         {
10298                 vec4_t layercolor;
10299                 int layertexrgbscale;
10300                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10301                 {
10302                         if (layerindex == 0)
10303                                 GL_AlphaTest(true);
10304                         else
10305                         {
10306                                 GL_AlphaTest(false);
10307                                 GL_DepthFunc(GL_EQUAL);
10308                         }
10309                 }
10310                 GL_DepthMask(layer->depthmask && writedepth);
10311                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10312                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10313                 {
10314                         layertexrgbscale = 4;
10315                         VectorScale(layer->color, 0.25f, layercolor);
10316                 }
10317                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10318                 {
10319                         layertexrgbscale = 2;
10320                         VectorScale(layer->color, 0.5f, layercolor);
10321                 }
10322                 else
10323                 {
10324                         layertexrgbscale = 1;
10325                         VectorScale(layer->color, 1.0f, layercolor);
10326                 }
10327                 layercolor[3] = layer->color[3];
10328                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10329                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10330                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10331                 switch (layer->type)
10332                 {
10333                 case TEXTURELAYERTYPE_LITTEXTURE:
10334                         // single-pass lightmapped texture with 2x rgbscale
10335                         R_Mesh_TexBind(0, r_texture_white);
10336                         R_Mesh_TexMatrix(0, NULL);
10337                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10338                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10339                         R_Mesh_TexBind(1, layer->texture);
10340                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10341                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10342                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10343                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10344                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10345                         else if (FAKELIGHT_ENABLED)
10346                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10347                         else if (rsurface.uselightmaptexture)
10348                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10349                         else
10350                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10351                         break;
10352                 case TEXTURELAYERTYPE_TEXTURE:
10353                         // singletexture unlit texture with transparency support
10354                         R_Mesh_TexBind(0, layer->texture);
10355                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10356                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10357                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10358                         R_Mesh_TexBind(1, 0);
10359                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10360                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10361                         break;
10362                 case TEXTURELAYERTYPE_FOG:
10363                         // singletexture fogging
10364                         if (layer->texture)
10365                         {
10366                                 R_Mesh_TexBind(0, layer->texture);
10367                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10368                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10369                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10370                         }
10371                         else
10372                         {
10373                                 R_Mesh_TexBind(0, 0);
10374                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10375                         }
10376                         R_Mesh_TexBind(1, 0);
10377                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10378                         // generate a color array for the fog pass
10379                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10380                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10381                         RSurf_DrawBatch();
10382                         break;
10383                 default:
10384                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10385                 }
10386         }
10387         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10388         {
10389                 GL_DepthFunc(GL_LEQUAL);
10390                 GL_AlphaTest(false);
10391         }
10392 }
10393
10394 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10395 {
10396         // OpenGL 1.1 - crusty old voodoo path
10397         qboolean applyfog;
10398         int layerindex;
10399         const texturelayer_t *layer;
10400         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);
10401         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10402
10403         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10404         {
10405                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10406                 {
10407                         if (layerindex == 0)
10408                                 GL_AlphaTest(true);
10409                         else
10410                         {
10411                                 GL_AlphaTest(false);
10412                                 GL_DepthFunc(GL_EQUAL);
10413                         }
10414                 }
10415                 GL_DepthMask(layer->depthmask && writedepth);
10416                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10417                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10418                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10419                 switch (layer->type)
10420                 {
10421                 case TEXTURELAYERTYPE_LITTEXTURE:
10422                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10423                         {
10424                                 // two-pass lit texture with 2x rgbscale
10425                                 // first the lightmap pass
10426                                 R_Mesh_TexBind(0, r_texture_white);
10427                                 R_Mesh_TexMatrix(0, NULL);
10428                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10429                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10430                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10431                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10432                                 else if (FAKELIGHT_ENABLED)
10433                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10434                                 else if (rsurface.uselightmaptexture)
10435                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10436                                 else
10437                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10438                                 // then apply the texture to it
10439                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10440                                 R_Mesh_TexBind(0, layer->texture);
10441                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10442                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10443                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10444                                 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);
10445                         }
10446                         else
10447                         {
10448                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10449                                 R_Mesh_TexBind(0, layer->texture);
10450                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10451                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10452                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10453                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10454                                         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);
10455                                 else if (FAKELIGHT_ENABLED)
10456                                         RSurf_DrawBatch_GL11_FakeLight(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);
10457                                 else
10458                                         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);
10459                         }
10460                         break;
10461                 case TEXTURELAYERTYPE_TEXTURE:
10462                         // singletexture unlit texture with transparency support
10463                         R_Mesh_TexBind(0, layer->texture);
10464                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10465                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10466                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10467                         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);
10468                         break;
10469                 case TEXTURELAYERTYPE_FOG:
10470                         // singletexture fogging
10471                         if (layer->texture)
10472                         {
10473                                 R_Mesh_TexBind(0, layer->texture);
10474                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10475                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10476                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10477                         }
10478                         else
10479                         {
10480                                 R_Mesh_TexBind(0, 0);
10481                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10482                         }
10483                         // generate a color array for the fog pass
10484                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10485                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10486                         RSurf_DrawBatch();
10487                         break;
10488                 default:
10489                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10490                 }
10491         }
10492         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10493         {
10494                 GL_DepthFunc(GL_LEQUAL);
10495                 GL_AlphaTest(false);
10496         }
10497 }
10498
10499 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10500 {
10501         int vi;
10502         int j;
10503         r_vertexgeneric_t *batchvertex;
10504         float c[4];
10505
10506 //      R_Mesh_ResetTextureState();
10507         R_SetupShader_Generic_NoTexture(false, false);
10508
10509         if(rsurface.texture && rsurface.texture->currentskinframe)
10510         {
10511                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10512                 c[3] *= rsurface.texture->currentalpha;
10513         }
10514         else
10515         {
10516                 c[0] = 1;
10517                 c[1] = 0;
10518                 c[2] = 1;
10519                 c[3] = 1;
10520         }
10521
10522         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10523         {
10524                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10525                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10526                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10527         }
10528
10529         // brighten it up (as texture value 127 means "unlit")
10530         c[0] *= 2 * r_refdef.view.colorscale;
10531         c[1] *= 2 * r_refdef.view.colorscale;
10532         c[2] *= 2 * r_refdef.view.colorscale;
10533
10534         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10535                 c[3] *= r_wateralpha.value;
10536
10537         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10538         {
10539                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10540                 GL_DepthMask(false);
10541         }
10542         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10543         {
10544                 GL_BlendFunc(GL_ONE, GL_ONE);
10545                 GL_DepthMask(false);
10546         }
10547         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10548         {
10549                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10550                 GL_DepthMask(false);
10551         }
10552         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10553         {
10554                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10555                 GL_DepthMask(false);
10556         }
10557         else
10558         {
10559                 GL_BlendFunc(GL_ONE, GL_ZERO);
10560                 GL_DepthMask(writedepth);
10561         }
10562
10563         if (r_showsurfaces.integer == 3)
10564         {
10565                 rsurface.passcolor4f = NULL;
10566
10567                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10568                 {
10569                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10570
10571                         rsurface.passcolor4f = NULL;
10572                         rsurface.passcolor4f_vertexbuffer = 0;
10573                         rsurface.passcolor4f_bufferoffset = 0;
10574                 }
10575                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10576                 {
10577                         qboolean applycolor = true;
10578                         float one = 1.0;
10579
10580                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10581
10582                         r_refdef.lightmapintensity = 1;
10583                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10584                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10585                 }
10586                 else if (FAKELIGHT_ENABLED)
10587                 {
10588                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10589
10590                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10591                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10592                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10593                 }
10594                 else
10595                 {
10596                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10597
10598                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10599                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10600                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10601                 }
10602
10603                 if(!rsurface.passcolor4f)
10604                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10605
10606                 RSurf_DrawBatch_GL11_ApplyAmbient();
10607                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10608                 if(r_refdef.fogenabled)
10609                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10610                 RSurf_DrawBatch_GL11_ClampColor();
10611
10612                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10613                 R_SetupShader_Generic_NoTexture(false, false);
10614                 RSurf_DrawBatch();
10615         }
10616         else if (!r_refdef.view.showdebug)
10617         {
10618                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10619                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10620                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10621                 {
10622                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10623                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10624                 }
10625                 R_Mesh_PrepareVertices_Generic_Unlock();
10626                 RSurf_DrawBatch();
10627         }
10628         else if (r_showsurfaces.integer == 4)
10629         {
10630                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10631                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10632                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10633                 {
10634                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10635                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10636                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10637                 }
10638                 R_Mesh_PrepareVertices_Generic_Unlock();
10639                 RSurf_DrawBatch();
10640         }
10641         else if (r_showsurfaces.integer == 2)
10642         {
10643                 const int *e;
10644                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10645                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10646                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10647                 {
10648                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10649                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10650                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10651                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10652                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10653                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10654                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10655                 }
10656                 R_Mesh_PrepareVertices_Generic_Unlock();
10657                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10658         }
10659         else
10660         {
10661                 int texturesurfaceindex;
10662                 int k;
10663                 const msurface_t *surface;
10664                 float surfacecolor4f[4];
10665                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10666                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10667                 vi = 0;
10668                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10669                 {
10670                         surface = texturesurfacelist[texturesurfaceindex];
10671                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10672                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10673                         for (j = 0;j < surface->num_vertices;j++)
10674                         {
10675                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10676                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10677                                 vi++;
10678                         }
10679                 }
10680                 R_Mesh_PrepareVertices_Generic_Unlock();
10681                 RSurf_DrawBatch();
10682         }
10683 }
10684
10685 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10686 {
10687         CHECKGLERROR
10688         RSurf_SetupDepthAndCulling();
10689         if (r_showsurfaces.integer)
10690         {
10691                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10692                 return;
10693         }
10694         switch (vid.renderpath)
10695         {
10696         case RENDERPATH_GL20:
10697         case RENDERPATH_D3D9:
10698         case RENDERPATH_D3D10:
10699         case RENDERPATH_D3D11:
10700         case RENDERPATH_SOFT:
10701         case RENDERPATH_GLES2:
10702                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10703                 break;
10704         case RENDERPATH_GL13:
10705         case RENDERPATH_GLES1:
10706                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10707                 break;
10708         case RENDERPATH_GL11:
10709                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10710                 break;
10711         }
10712         CHECKGLERROR
10713 }
10714
10715 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10716 {
10717         CHECKGLERROR
10718         RSurf_SetupDepthAndCulling();
10719         if (r_showsurfaces.integer)
10720         {
10721                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10722                 return;
10723         }
10724         switch (vid.renderpath)
10725         {
10726         case RENDERPATH_GL20:
10727         case RENDERPATH_D3D9:
10728         case RENDERPATH_D3D10:
10729         case RENDERPATH_D3D11:
10730         case RENDERPATH_SOFT:
10731         case RENDERPATH_GLES2:
10732                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10733                 break;
10734         case RENDERPATH_GL13:
10735         case RENDERPATH_GLES1:
10736                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10737                 break;
10738         case RENDERPATH_GL11:
10739                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10740                 break;
10741         }
10742         CHECKGLERROR
10743 }
10744
10745 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10746 {
10747         int i, j;
10748         int texturenumsurfaces, endsurface;
10749         texture_t *texture;
10750         const msurface_t *surface;
10751         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10752
10753         // if the model is static it doesn't matter what value we give for
10754         // wantnormals and wanttangents, so this logic uses only rules applicable
10755         // to a model, knowing that they are meaningless otherwise
10756         if (ent == r_refdef.scene.worldentity)
10757                 RSurf_ActiveWorldEntity();
10758         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10759                 RSurf_ActiveModelEntity(ent, false, false, false);
10760         else
10761         {
10762                 switch (vid.renderpath)
10763                 {
10764                 case RENDERPATH_GL20:
10765                 case RENDERPATH_D3D9:
10766                 case RENDERPATH_D3D10:
10767                 case RENDERPATH_D3D11:
10768                 case RENDERPATH_SOFT:
10769                 case RENDERPATH_GLES2:
10770                         RSurf_ActiveModelEntity(ent, true, true, false);
10771                         break;
10772                 case RENDERPATH_GL11:
10773                 case RENDERPATH_GL13:
10774                 case RENDERPATH_GLES1:
10775                         RSurf_ActiveModelEntity(ent, true, false, false);
10776                         break;
10777                 }
10778         }
10779
10780         if (r_transparentdepthmasking.integer)
10781         {
10782                 qboolean setup = false;
10783                 for (i = 0;i < numsurfaces;i = j)
10784                 {
10785                         j = i + 1;
10786                         surface = rsurface.modelsurfaces + surfacelist[i];
10787                         texture = surface->texture;
10788                         rsurface.texture = R_GetCurrentTexture(texture);
10789                         rsurface.lightmaptexture = NULL;
10790                         rsurface.deluxemaptexture = NULL;
10791                         rsurface.uselightmaptexture = false;
10792                         // scan ahead until we find a different texture
10793                         endsurface = min(i + 1024, numsurfaces);
10794                         texturenumsurfaces = 0;
10795                         texturesurfacelist[texturenumsurfaces++] = surface;
10796                         for (;j < endsurface;j++)
10797                         {
10798                                 surface = rsurface.modelsurfaces + surfacelist[j];
10799                                 if (texture != surface->texture)
10800                                         break;
10801                                 texturesurfacelist[texturenumsurfaces++] = surface;
10802                         }
10803                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10804                                 continue;
10805                         // render the range of surfaces as depth
10806                         if (!setup)
10807                         {
10808                                 setup = true;
10809                                 GL_ColorMask(0,0,0,0);
10810                                 GL_Color(1,1,1,1);
10811                                 GL_DepthTest(true);
10812                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10813                                 GL_DepthMask(true);
10814 //                              R_Mesh_ResetTextureState();
10815                                 R_SetupShader_DepthOrShadow(false, false);
10816                         }
10817                         RSurf_SetupDepthAndCulling();
10818                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10819                         if (rsurface.batchvertex3fbuffer)
10820                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10821                         else
10822                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10823                         RSurf_DrawBatch();
10824                 }
10825                 if (setup)
10826                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10827         }
10828
10829         for (i = 0;i < numsurfaces;i = j)
10830         {
10831                 j = i + 1;
10832                 surface = rsurface.modelsurfaces + surfacelist[i];
10833                 texture = surface->texture;
10834                 rsurface.texture = R_GetCurrentTexture(texture);
10835                 // scan ahead until we find a different texture
10836                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10837                 texturenumsurfaces = 0;
10838                 texturesurfacelist[texturenumsurfaces++] = surface;
10839                 if(FAKELIGHT_ENABLED)
10840                 {
10841                         rsurface.lightmaptexture = NULL;
10842                         rsurface.deluxemaptexture = NULL;
10843                         rsurface.uselightmaptexture = false;
10844                         for (;j < endsurface;j++)
10845                         {
10846                                 surface = rsurface.modelsurfaces + surfacelist[j];
10847                                 if (texture != surface->texture)
10848                                         break;
10849                                 texturesurfacelist[texturenumsurfaces++] = surface;
10850                         }
10851                 }
10852                 else
10853                 {
10854                         rsurface.lightmaptexture = surface->lightmaptexture;
10855                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10856                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10857                         for (;j < endsurface;j++)
10858                         {
10859                                 surface = rsurface.modelsurfaces + surfacelist[j];
10860                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10861                                         break;
10862                                 texturesurfacelist[texturenumsurfaces++] = surface;
10863                         }
10864                 }
10865                 // render the range of surfaces
10866                 if (ent == r_refdef.scene.worldentity)
10867                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10868                 else
10869                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10870         }
10871         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10872 }
10873
10874 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10875 {
10876         // transparent surfaces get pushed off into the transparent queue
10877         int surfacelistindex;
10878         const msurface_t *surface;
10879         vec3_t tempcenter, center;
10880         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10881         {
10882                 surface = texturesurfacelist[surfacelistindex];
10883                 if (r_transparent_sortsurfacesbynearest.integer)
10884                 {
10885                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10886                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10887                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10888                 }
10889                 else
10890                 {
10891                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10892                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10893                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10894                 }
10895                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10896                 if (rsurface.entity->transparent_offset) // transparent offset
10897                 {
10898                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10899                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10900                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10901                 }
10902                 R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10903         }
10904 }
10905
10906 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10907 {
10908         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10909                 return;
10910         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10911                 return;
10912         RSurf_SetupDepthAndCulling();
10913         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10914         if (rsurface.batchvertex3fbuffer)
10915                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10916         else
10917                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10918         RSurf_DrawBatch();
10919 }
10920
10921 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10922 {
10923         CHECKGLERROR
10924         if (depthonly)
10925                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10926         else if (prepass)
10927         {
10928                 if (!rsurface.texture->currentnumlayers)
10929                         return;
10930                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10931                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10932                 else
10933                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10934         }
10935         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10936                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10937         else if (!rsurface.texture->currentnumlayers)
10938                 return;
10939         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10940         {
10941                 // in the deferred case, transparent surfaces were queued during prepass
10942                 if (!r_shadow_usingdeferredprepass)
10943                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10944         }
10945         else
10946         {
10947                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10948                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10949         }
10950         CHECKGLERROR
10951 }
10952
10953 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10954 {
10955         int i, j;
10956         texture_t *texture;
10957         R_FrameData_SetMark();
10958         // break the surface list down into batches by texture and use of lightmapping
10959         for (i = 0;i < numsurfaces;i = j)
10960         {
10961                 j = i + 1;
10962                 // texture is the base texture pointer, rsurface.texture is the
10963                 // current frame/skin the texture is directing us to use (for example
10964                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10965                 // use skin 1 instead)
10966                 texture = surfacelist[i]->texture;
10967                 rsurface.texture = R_GetCurrentTexture(texture);
10968                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10969                 {
10970                         // if this texture is not the kind we want, skip ahead to the next one
10971                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10972                                 ;
10973                         continue;
10974                 }
10975                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10976                 {
10977                         rsurface.lightmaptexture = NULL;
10978                         rsurface.deluxemaptexture = NULL;
10979                         rsurface.uselightmaptexture = false;
10980                         // simply scan ahead until we find a different texture or lightmap state
10981                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10982                                 ;
10983                 }
10984                 else
10985                 {
10986                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10987                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10988                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10989                         // simply scan ahead until we find a different texture or lightmap state
10990                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10991                                 ;
10992                 }
10993                 // render the range of surfaces
10994                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10995         }
10996         R_FrameData_ReturnToMark();
10997 }
10998
10999 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11000 {
11001         CHECKGLERROR
11002         if (depthonly)
11003                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11004         else if (prepass)
11005         {
11006                 if (!rsurface.texture->currentnumlayers)
11007                         return;
11008                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11009                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11010                 else
11011                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11012         }
11013         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11014                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11015         else if (!rsurface.texture->currentnumlayers)
11016                 return;
11017         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11018         {
11019                 // in the deferred case, transparent surfaces were queued during prepass
11020                 if (!r_shadow_usingdeferredprepass)
11021                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11022         }
11023         else
11024         {
11025                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11026                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11027         }
11028         CHECKGLERROR
11029 }
11030
11031 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11032 {
11033         int i, j;
11034         texture_t *texture;
11035         R_FrameData_SetMark();
11036         // break the surface list down into batches by texture and use of lightmapping
11037         for (i = 0;i < numsurfaces;i = j)
11038         {
11039                 j = i + 1;
11040                 // texture is the base texture pointer, rsurface.texture is the
11041                 // current frame/skin the texture is directing us to use (for example
11042                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11043                 // use skin 1 instead)
11044                 texture = surfacelist[i]->texture;
11045                 rsurface.texture = R_GetCurrentTexture(texture);
11046                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11047                 {
11048                         // if this texture is not the kind we want, skip ahead to the next one
11049                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11050                                 ;
11051                         continue;
11052                 }
11053                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11054                 {
11055                         rsurface.lightmaptexture = NULL;
11056                         rsurface.deluxemaptexture = NULL;
11057                         rsurface.uselightmaptexture = false;
11058                         // simply scan ahead until we find a different texture or lightmap state
11059                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11060                                 ;
11061                 }
11062                 else
11063                 {
11064                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11065                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11066                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11067                         // simply scan ahead until we find a different texture or lightmap state
11068                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11069                                 ;
11070                 }
11071                 // render the range of surfaces
11072                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11073         }
11074         R_FrameData_ReturnToMark();
11075 }
11076
11077 float locboxvertex3f[6*4*3] =
11078 {
11079         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11080         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11081         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11082         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11083         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11084         1,0,0, 0,0,0, 0,1,0, 1,1,0
11085 };
11086
11087 unsigned short locboxelements[6*2*3] =
11088 {
11089          0, 1, 2, 0, 2, 3,
11090          4, 5, 6, 4, 6, 7,
11091          8, 9,10, 8,10,11,
11092         12,13,14, 12,14,15,
11093         16,17,18, 16,18,19,
11094         20,21,22, 20,22,23
11095 };
11096
11097 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11098 {
11099         int i, j;
11100         cl_locnode_t *loc = (cl_locnode_t *)ent;
11101         vec3_t mins, size;
11102         float vertex3f[6*4*3];
11103         CHECKGLERROR
11104         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11105         GL_DepthMask(false);
11106         GL_DepthRange(0, 1);
11107         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11108         GL_DepthTest(true);
11109         GL_CullFace(GL_NONE);
11110         R_EntityMatrix(&identitymatrix);
11111
11112 //      R_Mesh_ResetTextureState();
11113
11114         i = surfacelist[0];
11115         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11116                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11117                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11118                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11119
11120         if (VectorCompare(loc->mins, loc->maxs))
11121         {
11122                 VectorSet(size, 2, 2, 2);
11123                 VectorMA(loc->mins, -0.5f, size, mins);
11124         }
11125         else
11126         {
11127                 VectorCopy(loc->mins, mins);
11128                 VectorSubtract(loc->maxs, loc->mins, size);
11129         }
11130
11131         for (i = 0;i < 6*4*3;)
11132                 for (j = 0;j < 3;j++, i++)
11133                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11134
11135         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11136         R_SetupShader_Generic_NoTexture(false, false);
11137         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11138 }
11139
11140 void R_DrawLocs(void)
11141 {
11142         int index;
11143         cl_locnode_t *loc, *nearestloc;
11144         vec3_t center;
11145         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11146         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11147         {
11148                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11149                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11150         }
11151 }
11152
11153 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11154 {
11155         if (decalsystem->decals)
11156                 Mem_Free(decalsystem->decals);
11157         memset(decalsystem, 0, sizeof(*decalsystem));
11158 }
11159
11160 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)
11161 {
11162         tridecal_t *decal;
11163         tridecal_t *decals;
11164         int i;
11165
11166         // expand or initialize the system
11167         if (decalsystem->maxdecals <= decalsystem->numdecals)
11168         {
11169                 decalsystem_t old = *decalsystem;
11170                 qboolean useshortelements;
11171                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11172                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11173                 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)));
11174                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11175                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11176                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11177                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11178                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11179                 if (decalsystem->numdecals)
11180                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11181                 if (old.decals)
11182                         Mem_Free(old.decals);
11183                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11184                         decalsystem->element3i[i] = i;
11185                 if (useshortelements)
11186                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11187                                 decalsystem->element3s[i] = i;
11188         }
11189
11190         // grab a decal and search for another free slot for the next one
11191         decals = decalsystem->decals;
11192         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11193         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11194                 ;
11195         decalsystem->freedecal = i;
11196         if (decalsystem->numdecals <= i)
11197                 decalsystem->numdecals = i + 1;
11198
11199         // initialize the decal
11200         decal->lived = 0;
11201         decal->triangleindex = triangleindex;
11202         decal->surfaceindex = surfaceindex;
11203         decal->decalsequence = decalsequence;
11204         decal->color4f[0][0] = c0[0];
11205         decal->color4f[0][1] = c0[1];
11206         decal->color4f[0][2] = c0[2];
11207         decal->color4f[0][3] = 1;
11208         decal->color4f[1][0] = c1[0];
11209         decal->color4f[1][1] = c1[1];
11210         decal->color4f[1][2] = c1[2];
11211         decal->color4f[1][3] = 1;
11212         decal->color4f[2][0] = c2[0];
11213         decal->color4f[2][1] = c2[1];
11214         decal->color4f[2][2] = c2[2];
11215         decal->color4f[2][3] = 1;
11216         decal->vertex3f[0][0] = v0[0];
11217         decal->vertex3f[0][1] = v0[1];
11218         decal->vertex3f[0][2] = v0[2];
11219         decal->vertex3f[1][0] = v1[0];
11220         decal->vertex3f[1][1] = v1[1];
11221         decal->vertex3f[1][2] = v1[2];
11222         decal->vertex3f[2][0] = v2[0];
11223         decal->vertex3f[2][1] = v2[1];
11224         decal->vertex3f[2][2] = v2[2];
11225         decal->texcoord2f[0][0] = t0[0];
11226         decal->texcoord2f[0][1] = t0[1];
11227         decal->texcoord2f[1][0] = t1[0];
11228         decal->texcoord2f[1][1] = t1[1];
11229         decal->texcoord2f[2][0] = t2[0];
11230         decal->texcoord2f[2][1] = t2[1];
11231         TriangleNormal(v0, v1, v2, decal->plane);
11232         VectorNormalize(decal->plane);
11233         decal->plane[3] = DotProduct(v0, decal->plane);
11234 }
11235
11236 extern cvar_t cl_decals_bias;
11237 extern cvar_t cl_decals_models;
11238 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11239 // baseparms, parms, temps
11240 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)
11241 {
11242         int cornerindex;
11243         int index;
11244         float v[9][3];
11245         const float *vertex3f;
11246         const float *normal3f;
11247         int numpoints;
11248         float points[2][9][3];
11249         float temp[3];
11250         float tc[9][2];
11251         float f;
11252         float c[9][4];
11253         const int *e;
11254
11255         e = rsurface.modelelement3i + 3*triangleindex;
11256
11257         vertex3f = rsurface.modelvertex3f;
11258         normal3f = rsurface.modelnormal3f;
11259
11260         if (normal3f)
11261         {
11262                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11263                 {
11264                         index = 3*e[cornerindex];
11265                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11266                 }
11267         }
11268         else
11269         {
11270                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11271                 {
11272                         index = 3*e[cornerindex];
11273                         VectorCopy(vertex3f + index, v[cornerindex]);
11274                 }
11275         }
11276
11277         // cull backfaces
11278         //TriangleNormal(v[0], v[1], v[2], normal);
11279         //if (DotProduct(normal, localnormal) < 0.0f)
11280         //      continue;
11281         // clip by each of the box planes formed from the projection matrix
11282         // if anything survives, we emit the decal
11283         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]);
11284         if (numpoints < 3)
11285                 return;
11286         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]);
11287         if (numpoints < 3)
11288                 return;
11289         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]);
11290         if (numpoints < 3)
11291                 return;
11292         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]);
11293         if (numpoints < 3)
11294                 return;
11295         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]);
11296         if (numpoints < 3)
11297                 return;
11298         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]);
11299         if (numpoints < 3)
11300                 return;
11301         // some part of the triangle survived, so we have to accept it...
11302         if (dynamic)
11303         {
11304                 // dynamic always uses the original triangle
11305                 numpoints = 3;
11306                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11307                 {
11308                         index = 3*e[cornerindex];
11309                         VectorCopy(vertex3f + index, v[cornerindex]);
11310                 }
11311         }
11312         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11313         {
11314                 // convert vertex positions to texcoords
11315                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11316                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11317                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11318                 // calculate distance fade from the projection origin
11319                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11320                 f = bound(0.0f, f, 1.0f);
11321                 c[cornerindex][0] = r * f;
11322                 c[cornerindex][1] = g * f;
11323                 c[cornerindex][2] = b * f;
11324                 c[cornerindex][3] = 1.0f;
11325                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11326         }
11327         if (dynamic)
11328                 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);
11329         else
11330                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11331                         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);
11332 }
11333 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)
11334 {
11335         matrix4x4_t projection;
11336         decalsystem_t *decalsystem;
11337         qboolean dynamic;
11338         dp_model_t *model;
11339         const msurface_t *surface;
11340         const msurface_t *surfaces;
11341         const int *surfacelist;
11342         const texture_t *texture;
11343         int numtriangles;
11344         int numsurfacelist;
11345         int surfacelistindex;
11346         int surfaceindex;
11347         int triangleindex;
11348         float localorigin[3];
11349         float localnormal[3];
11350         float localmins[3];
11351         float localmaxs[3];
11352         float localsize;
11353         //float normal[3];
11354         float planes[6][4];
11355         float angles[3];
11356         bih_t *bih;
11357         int bih_triangles_count;
11358         int bih_triangles[256];
11359         int bih_surfaces[256];
11360
11361         decalsystem = &ent->decalsystem;
11362         model = ent->model;
11363         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11364         {
11365                 R_DecalSystem_Reset(&ent->decalsystem);
11366                 return;
11367         }
11368
11369         if (!model->brush.data_leafs && !cl_decals_models.integer)
11370         {
11371                 if (decalsystem->model)
11372                         R_DecalSystem_Reset(decalsystem);
11373                 return;
11374         }
11375
11376         if (decalsystem->model != model)
11377                 R_DecalSystem_Reset(decalsystem);
11378         decalsystem->model = model;
11379
11380         RSurf_ActiveModelEntity(ent, true, false, false);
11381
11382         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11383         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11384         VectorNormalize(localnormal);
11385         localsize = worldsize*rsurface.inversematrixscale;
11386         localmins[0] = localorigin[0] - localsize;
11387         localmins[1] = localorigin[1] - localsize;
11388         localmins[2] = localorigin[2] - localsize;
11389         localmaxs[0] = localorigin[0] + localsize;
11390         localmaxs[1] = localorigin[1] + localsize;
11391         localmaxs[2] = localorigin[2] + localsize;
11392
11393         //VectorCopy(localnormal, planes[4]);
11394         //VectorVectors(planes[4], planes[2], planes[0]);
11395         AnglesFromVectors(angles, localnormal, NULL, false);
11396         AngleVectors(angles, planes[0], planes[2], planes[4]);
11397         VectorNegate(planes[0], planes[1]);
11398         VectorNegate(planes[2], planes[3]);
11399         VectorNegate(planes[4], planes[5]);
11400         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11401         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11402         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11403         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11404         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11405         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11406
11407 #if 1
11408 // works
11409 {
11410         matrix4x4_t forwardprojection;
11411         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11412         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11413 }
11414 #else
11415 // broken
11416 {
11417         float projectionvector[4][3];
11418         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11419         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11420         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11421         projectionvector[0][0] = planes[0][0] * ilocalsize;
11422         projectionvector[0][1] = planes[1][0] * ilocalsize;
11423         projectionvector[0][2] = planes[2][0] * ilocalsize;
11424         projectionvector[1][0] = planes[0][1] * ilocalsize;
11425         projectionvector[1][1] = planes[1][1] * ilocalsize;
11426         projectionvector[1][2] = planes[2][1] * ilocalsize;
11427         projectionvector[2][0] = planes[0][2] * ilocalsize;
11428         projectionvector[2][1] = planes[1][2] * ilocalsize;
11429         projectionvector[2][2] = planes[2][2] * ilocalsize;
11430         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11431         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11432         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11433         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11434 }
11435 #endif
11436
11437         dynamic = model->surfmesh.isanimated;
11438         numsurfacelist = model->nummodelsurfaces;
11439         surfacelist = model->sortedmodelsurfaces;
11440         surfaces = model->data_surfaces;
11441
11442         bih = NULL;
11443         bih_triangles_count = -1;
11444         if(!dynamic)
11445         {
11446                 if(model->render_bih.numleafs)
11447                         bih = &model->render_bih;
11448                 else if(model->collision_bih.numleafs)
11449                         bih = &model->collision_bih;
11450         }
11451         if(bih)
11452                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11453         if(bih_triangles_count == 0)
11454                 return;
11455         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11456                 return;
11457         if(bih_triangles_count > 0)
11458         {
11459                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11460                 {
11461                         surfaceindex = bih_surfaces[triangleindex];
11462                         surface = surfaces + surfaceindex;
11463                         texture = surface->texture;
11464                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11465                                 continue;
11466                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11467                                 continue;
11468                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11469                 }
11470         }
11471         else
11472         {
11473                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11474                 {
11475                         surfaceindex = surfacelist[surfacelistindex];
11476                         surface = surfaces + surfaceindex;
11477                         // check cull box first because it rejects more than any other check
11478                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11479                                 continue;
11480                         // skip transparent surfaces
11481                         texture = surface->texture;
11482                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11483                                 continue;
11484                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11485                                 continue;
11486                         numtriangles = surface->num_triangles;
11487                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11488                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11489                 }
11490         }
11491 }
11492
11493 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11494 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)
11495 {
11496         int renderentityindex;
11497         float worldmins[3];
11498         float worldmaxs[3];
11499         entity_render_t *ent;
11500
11501         if (!cl_decals_newsystem.integer)
11502                 return;
11503
11504         worldmins[0] = worldorigin[0] - worldsize;
11505         worldmins[1] = worldorigin[1] - worldsize;
11506         worldmins[2] = worldorigin[2] - worldsize;
11507         worldmaxs[0] = worldorigin[0] + worldsize;
11508         worldmaxs[1] = worldorigin[1] + worldsize;
11509         worldmaxs[2] = worldorigin[2] + worldsize;
11510
11511         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11512
11513         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11514         {
11515                 ent = r_refdef.scene.entities[renderentityindex];
11516                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11517                         continue;
11518
11519                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11520         }
11521 }
11522
11523 typedef struct r_decalsystem_splatqueue_s
11524 {
11525         vec3_t worldorigin;
11526         vec3_t worldnormal;
11527         float color[4];
11528         float tcrange[4];
11529         float worldsize;
11530         int decalsequence;
11531 }
11532 r_decalsystem_splatqueue_t;
11533
11534 int r_decalsystem_numqueued = 0;
11535 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11536
11537 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)
11538 {
11539         r_decalsystem_splatqueue_t *queue;
11540
11541         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11542                 return;
11543
11544         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11545         VectorCopy(worldorigin, queue->worldorigin);
11546         VectorCopy(worldnormal, queue->worldnormal);
11547         Vector4Set(queue->color, r, g, b, a);
11548         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11549         queue->worldsize = worldsize;
11550         queue->decalsequence = cl.decalsequence++;
11551 }
11552
11553 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11554 {
11555         int i;
11556         r_decalsystem_splatqueue_t *queue;
11557
11558         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11559                 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);
11560         r_decalsystem_numqueued = 0;
11561 }
11562
11563 extern cvar_t cl_decals_max;
11564 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11565 {
11566         int i;
11567         decalsystem_t *decalsystem = &ent->decalsystem;
11568         int numdecals;
11569         int killsequence;
11570         tridecal_t *decal;
11571         float frametime;
11572         float lifetime;
11573
11574         if (!decalsystem->numdecals)
11575                 return;
11576
11577         if (r_showsurfaces.integer)
11578                 return;
11579
11580         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11581         {
11582                 R_DecalSystem_Reset(decalsystem);
11583                 return;
11584         }
11585
11586         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11587         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11588
11589         if (decalsystem->lastupdatetime)
11590                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11591         else
11592                 frametime = 0;
11593         decalsystem->lastupdatetime = r_refdef.scene.time;
11594         numdecals = decalsystem->numdecals;
11595
11596         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11597         {
11598                 if (decal->color4f[0][3])
11599                 {
11600                         decal->lived += frametime;
11601                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11602                         {
11603                                 memset(decal, 0, sizeof(*decal));
11604                                 if (decalsystem->freedecal > i)
11605                                         decalsystem->freedecal = i;
11606                         }
11607                 }
11608         }
11609         decal = decalsystem->decals;
11610         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11611                 numdecals--;
11612
11613         // collapse the array by shuffling the tail decals into the gaps
11614         for (;;)
11615         {
11616                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11617                         decalsystem->freedecal++;
11618                 if (decalsystem->freedecal == numdecals)
11619                         break;
11620                 decal[decalsystem->freedecal] = decal[--numdecals];
11621         }
11622
11623         decalsystem->numdecals = numdecals;
11624
11625         if (numdecals <= 0)
11626         {
11627                 // if there are no decals left, reset decalsystem
11628                 R_DecalSystem_Reset(decalsystem);
11629         }
11630 }
11631
11632 extern skinframe_t *decalskinframe;
11633 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11634 {
11635         int i;
11636         decalsystem_t *decalsystem = &ent->decalsystem;
11637         int numdecals;
11638         tridecal_t *decal;
11639         float faderate;
11640         float alpha;
11641         float *v3f;
11642         float *c4f;
11643         float *t2f;
11644         const int *e;
11645         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11646         int numtris = 0;
11647
11648         numdecals = decalsystem->numdecals;
11649         if (!numdecals)
11650                 return;
11651
11652         if (r_showsurfaces.integer)
11653                 return;
11654
11655         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11656         {
11657                 R_DecalSystem_Reset(decalsystem);
11658                 return;
11659         }
11660
11661         // if the model is static it doesn't matter what value we give for
11662         // wantnormals and wanttangents, so this logic uses only rules applicable
11663         // to a model, knowing that they are meaningless otherwise
11664         if (ent == r_refdef.scene.worldentity)
11665                 RSurf_ActiveWorldEntity();
11666         else
11667                 RSurf_ActiveModelEntity(ent, false, false, false);
11668
11669         decalsystem->lastupdatetime = r_refdef.scene.time;
11670
11671         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11672
11673         // update vertex positions for animated models
11674         v3f = decalsystem->vertex3f;
11675         c4f = decalsystem->color4f;
11676         t2f = decalsystem->texcoord2f;
11677         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11678         {
11679                 if (!decal->color4f[0][3])
11680                         continue;
11681
11682                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11683                         continue;
11684
11685                 // skip backfaces
11686                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11687                         continue;
11688
11689                 // update color values for fading decals
11690                 if (decal->lived >= cl_decals_time.value)
11691                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11692                 else
11693                         alpha = 1.0f;
11694
11695                 c4f[ 0] = decal->color4f[0][0] * alpha;
11696                 c4f[ 1] = decal->color4f[0][1] * alpha;
11697                 c4f[ 2] = decal->color4f[0][2] * alpha;
11698                 c4f[ 3] = 1;
11699                 c4f[ 4] = decal->color4f[1][0] * alpha;
11700                 c4f[ 5] = decal->color4f[1][1] * alpha;
11701                 c4f[ 6] = decal->color4f[1][2] * alpha;
11702                 c4f[ 7] = 1;
11703                 c4f[ 8] = decal->color4f[2][0] * alpha;
11704                 c4f[ 9] = decal->color4f[2][1] * alpha;
11705                 c4f[10] = decal->color4f[2][2] * alpha;
11706                 c4f[11] = 1;
11707
11708                 t2f[0] = decal->texcoord2f[0][0];
11709                 t2f[1] = decal->texcoord2f[0][1];
11710                 t2f[2] = decal->texcoord2f[1][0];
11711                 t2f[3] = decal->texcoord2f[1][1];
11712                 t2f[4] = decal->texcoord2f[2][0];
11713                 t2f[5] = decal->texcoord2f[2][1];
11714
11715                 // update vertex positions for animated models
11716                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11717                 {
11718                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11719                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11720                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11721                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11722                 }
11723                 else
11724                 {
11725                         VectorCopy(decal->vertex3f[0], v3f);
11726                         VectorCopy(decal->vertex3f[1], v3f + 3);
11727                         VectorCopy(decal->vertex3f[2], v3f + 6);
11728                 }
11729
11730                 if (r_refdef.fogenabled)
11731                 {
11732                         alpha = RSurf_FogVertex(v3f);
11733                         VectorScale(c4f, alpha, c4f);
11734                         alpha = RSurf_FogVertex(v3f + 3);
11735                         VectorScale(c4f + 4, alpha, c4f + 4);
11736                         alpha = RSurf_FogVertex(v3f + 6);
11737                         VectorScale(c4f + 8, alpha, c4f + 8);
11738                 }
11739
11740                 v3f += 9;
11741                 c4f += 12;
11742                 t2f += 6;
11743                 numtris++;
11744         }
11745
11746         if (numtris > 0)
11747         {
11748                 r_refdef.stats.drawndecals += numtris;
11749
11750                 // now render the decals all at once
11751                 // (this assumes they all use one particle font texture!)
11752                 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);
11753 //              R_Mesh_ResetTextureState();
11754                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11755                 GL_DepthMask(false);
11756                 GL_DepthRange(0, 1);
11757                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11758                 GL_DepthTest(true);
11759                 GL_CullFace(GL_NONE);
11760                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11761                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11762                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11763         }
11764 }
11765
11766 static void R_DrawModelDecals(void)
11767 {
11768         int i, numdecals;
11769
11770         // fade faster when there are too many decals
11771         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11772         for (i = 0;i < r_refdef.scene.numentities;i++)
11773                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11774
11775         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11776         for (i = 0;i < r_refdef.scene.numentities;i++)
11777                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11778                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11779
11780         R_DecalSystem_ApplySplatEntitiesQueue();
11781
11782         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11783         for (i = 0;i < r_refdef.scene.numentities;i++)
11784                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11785
11786         r_refdef.stats.totaldecals += numdecals;
11787
11788         if (r_showsurfaces.integer)
11789                 return;
11790
11791         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11792
11793         for (i = 0;i < r_refdef.scene.numentities;i++)
11794         {
11795                 if (!r_refdef.viewcache.entityvisible[i])
11796                         continue;
11797                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11798                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11799         }
11800 }
11801
11802 extern cvar_t mod_collision_bih;
11803 static void R_DrawDebugModel(void)
11804 {
11805         entity_render_t *ent = rsurface.entity;
11806         int i, j, k, l, flagsmask;
11807         const msurface_t *surface;
11808         dp_model_t *model = ent->model;
11809         vec3_t v;
11810
11811         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11812                 return;
11813
11814         if (r_showoverdraw.value > 0)
11815         {
11816                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11817                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11818                 R_SetupShader_Generic_NoTexture(false, false);
11819                 GL_DepthTest(false);
11820                 GL_DepthMask(false);
11821                 GL_DepthRange(0, 1);
11822                 GL_BlendFunc(GL_ONE, GL_ONE);
11823                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11824                 {
11825                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11826                                 continue;
11827                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11828                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11829                         {
11830                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11831                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11832                                 if (!rsurface.texture->currentlayers->depthmask)
11833                                         GL_Color(c, 0, 0, 1.0f);
11834                                 else if (ent == r_refdef.scene.worldentity)
11835                                         GL_Color(c, c, c, 1.0f);
11836                                 else
11837                                         GL_Color(0, c, 0, 1.0f);
11838                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11839                                 RSurf_DrawBatch();
11840                         }
11841                 }
11842                 rsurface.texture = NULL;
11843         }
11844
11845         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11846
11847 //      R_Mesh_ResetTextureState();
11848         R_SetupShader_Generic_NoTexture(false, false);
11849         GL_DepthRange(0, 1);
11850         GL_DepthTest(!r_showdisabledepthtest.integer);
11851         GL_DepthMask(false);
11852         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11853
11854         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11855         {
11856                 int triangleindex;
11857                 int bihleafindex;
11858                 qboolean cullbox = false;
11859                 const q3mbrush_t *brush;
11860                 const bih_t *bih = &model->collision_bih;
11861                 const bih_leaf_t *bihleaf;
11862                 float vertex3f[3][3];
11863                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11864                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11865                 {
11866                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11867                                 continue;
11868                         switch (bihleaf->type)
11869                         {
11870                         case BIH_BRUSH:
11871                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11872                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11873                                 {
11874                                         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);
11875                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11876                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11877                                 }
11878                                 break;
11879                         case BIH_COLLISIONTRIANGLE:
11880                                 triangleindex = bihleaf->itemindex;
11881                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11882                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11883                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11884                                 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);
11885                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11886                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11887                                 break;
11888                         case BIH_RENDERTRIANGLE:
11889                                 triangleindex = bihleaf->itemindex;
11890                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11891                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11892                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11893                                 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);
11894                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11895                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11896                                 break;
11897                         }
11898                 }
11899         }
11900
11901         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11902
11903 #ifndef USE_GLES2
11904         if (r_showtris.integer && qglPolygonMode)
11905         {
11906                 if (r_showdisabledepthtest.integer)
11907                 {
11908                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11909                         GL_DepthMask(false);
11910                 }
11911                 else
11912                 {
11913                         GL_BlendFunc(GL_ONE, GL_ZERO);
11914                         GL_DepthMask(true);
11915                 }
11916                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11917                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11918                 {
11919                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11920                                 continue;
11921                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11922                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11923                         {
11924                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11925                                 if (!rsurface.texture->currentlayers->depthmask)
11926                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11927                                 else if (ent == r_refdef.scene.worldentity)
11928                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11929                                 else
11930                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11931                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11932                                 RSurf_DrawBatch();
11933                         }
11934                 }
11935                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11936                 rsurface.texture = NULL;
11937         }
11938
11939         if (r_shownormals.value != 0 && qglBegin)
11940         {
11941                 if (r_showdisabledepthtest.integer)
11942                 {
11943                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11944                         GL_DepthMask(false);
11945                 }
11946                 else
11947                 {
11948                         GL_BlendFunc(GL_ONE, GL_ZERO);
11949                         GL_DepthMask(true);
11950                 }
11951                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11952                 {
11953                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11954                                 continue;
11955                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11956                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11957                         {
11958                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11959                                 qglBegin(GL_LINES);
11960                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11961                                 {
11962                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11963                                         {
11964                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11965                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11966                                                 qglVertex3f(v[0], v[1], v[2]);
11967                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11968                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11969                                                 qglVertex3f(v[0], v[1], v[2]);
11970                                         }
11971                                 }
11972                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11973                                 {
11974                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11975                                         {
11976                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11977                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11978                                                 qglVertex3f(v[0], v[1], v[2]);
11979                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11980                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11981                                                 qglVertex3f(v[0], v[1], v[2]);
11982                                         }
11983                                 }
11984                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11985                                 {
11986                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11987                                         {
11988                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11989                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11990                                                 qglVertex3f(v[0], v[1], v[2]);
11991                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11992                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11993                                                 qglVertex3f(v[0], v[1], v[2]);
11994                                         }
11995                                 }
11996                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11997                                 {
11998                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11999                                         {
12000                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12001                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12002                                                 qglVertex3f(v[0], v[1], v[2]);
12003                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12004                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12005                                                 qglVertex3f(v[0], v[1], v[2]);
12006                                         }
12007                                 }
12008                                 qglEnd();
12009                                 CHECKGLERROR
12010                         }
12011                 }
12012                 rsurface.texture = NULL;
12013         }
12014 #endif
12015 }
12016
12017 int r_maxsurfacelist = 0;
12018 const msurface_t **r_surfacelist = NULL;
12019 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12020 {
12021         int i, j, endj, flagsmask;
12022         dp_model_t *model = r_refdef.scene.worldmodel;
12023         msurface_t *surfaces;
12024         unsigned char *update;
12025         int numsurfacelist = 0;
12026         if (model == NULL)
12027                 return;
12028
12029         if (r_maxsurfacelist < model->num_surfaces)
12030         {
12031                 r_maxsurfacelist = model->num_surfaces;
12032                 if (r_surfacelist)
12033                         Mem_Free((msurface_t**)r_surfacelist);
12034                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12035         }
12036
12037         RSurf_ActiveWorldEntity();
12038
12039         surfaces = model->data_surfaces;
12040         update = model->brushq1.lightmapupdateflags;
12041
12042         // update light styles on this submodel
12043         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12044         {
12045                 model_brush_lightstyleinfo_t *style;
12046                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12047                 {
12048                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12049                         {
12050                                 int *list = style->surfacelist;
12051                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12052                                 for (j = 0;j < style->numsurfaces;j++)
12053                                         update[list[j]] = true;
12054                         }
12055                 }
12056         }
12057
12058         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12059
12060         if (debug)
12061         {
12062                 R_DrawDebugModel();
12063                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12064                 return;
12065         }
12066
12067         rsurface.lightmaptexture = NULL;
12068         rsurface.deluxemaptexture = NULL;
12069         rsurface.uselightmaptexture = false;
12070         rsurface.texture = NULL;
12071         rsurface.rtlight = NULL;
12072         numsurfacelist = 0;
12073         // add visible surfaces to draw list
12074         for (i = 0;i < model->nummodelsurfaces;i++)
12075         {
12076                 j = model->sortedmodelsurfaces[i];
12077                 if (r_refdef.viewcache.world_surfacevisible[j])
12078                         r_surfacelist[numsurfacelist++] = surfaces + j;
12079         }
12080         // update lightmaps if needed
12081         if (model->brushq1.firstrender)
12082         {
12083                 model->brushq1.firstrender = false;
12084                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12085                         if (update[j])
12086                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12087         }
12088         else if (update)
12089         {
12090                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12091                         if (r_refdef.viewcache.world_surfacevisible[j])
12092                                 if (update[j])
12093                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12094         }
12095         // don't do anything if there were no surfaces
12096         if (!numsurfacelist)
12097         {
12098                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12099                 return;
12100         }
12101         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12102
12103         // add to stats if desired
12104         if (r_speeds.integer && !skysurfaces && !depthonly)
12105         {
12106                 r_refdef.stats.world_surfaces += numsurfacelist;
12107                 for (j = 0;j < numsurfacelist;j++)
12108                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12109         }
12110
12111         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12112 }
12113
12114 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12115 {
12116         int i, j, endj, flagsmask;
12117         dp_model_t *model = ent->model;
12118         msurface_t *surfaces;
12119         unsigned char *update;
12120         int numsurfacelist = 0;
12121         if (model == NULL)
12122                 return;
12123
12124         if (r_maxsurfacelist < model->num_surfaces)
12125         {
12126                 r_maxsurfacelist = model->num_surfaces;
12127                 if (r_surfacelist)
12128                         Mem_Free((msurface_t **)r_surfacelist);
12129                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12130         }
12131
12132         // if the model is static it doesn't matter what value we give for
12133         // wantnormals and wanttangents, so this logic uses only rules applicable
12134         // to a model, knowing that they are meaningless otherwise
12135         if (ent == r_refdef.scene.worldentity)
12136                 RSurf_ActiveWorldEntity();
12137         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12138                 RSurf_ActiveModelEntity(ent, false, false, false);
12139         else if (prepass)
12140                 RSurf_ActiveModelEntity(ent, true, true, true);
12141         else if (depthonly)
12142         {
12143                 switch (vid.renderpath)
12144                 {
12145                 case RENDERPATH_GL20:
12146                 case RENDERPATH_D3D9:
12147                 case RENDERPATH_D3D10:
12148                 case RENDERPATH_D3D11:
12149                 case RENDERPATH_SOFT:
12150                 case RENDERPATH_GLES2:
12151                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12152                         break;
12153                 case RENDERPATH_GL11:
12154                 case RENDERPATH_GL13:
12155                 case RENDERPATH_GLES1:
12156                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12157                         break;
12158                 }
12159         }
12160         else
12161         {
12162                 switch (vid.renderpath)
12163                 {
12164                 case RENDERPATH_GL20:
12165                 case RENDERPATH_D3D9:
12166                 case RENDERPATH_D3D10:
12167                 case RENDERPATH_D3D11:
12168                 case RENDERPATH_SOFT:
12169                 case RENDERPATH_GLES2:
12170                         RSurf_ActiveModelEntity(ent, true, true, false);
12171                         break;
12172                 case RENDERPATH_GL11:
12173                 case RENDERPATH_GL13:
12174                 case RENDERPATH_GLES1:
12175                         RSurf_ActiveModelEntity(ent, true, false, false);
12176                         break;
12177                 }
12178         }
12179
12180         surfaces = model->data_surfaces;
12181         update = model->brushq1.lightmapupdateflags;
12182
12183         // update light styles
12184         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12185         {
12186                 model_brush_lightstyleinfo_t *style;
12187                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12188                 {
12189                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12190                         {
12191                                 int *list = style->surfacelist;
12192                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12193                                 for (j = 0;j < style->numsurfaces;j++)
12194                                         update[list[j]] = true;
12195                         }
12196                 }
12197         }
12198
12199         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12200
12201         if (debug)
12202         {
12203                 R_DrawDebugModel();
12204                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12205                 return;
12206         }
12207
12208         rsurface.lightmaptexture = NULL;
12209         rsurface.deluxemaptexture = NULL;
12210         rsurface.uselightmaptexture = false;
12211         rsurface.texture = NULL;
12212         rsurface.rtlight = NULL;
12213         numsurfacelist = 0;
12214         // add visible surfaces to draw list
12215         for (i = 0;i < model->nummodelsurfaces;i++)
12216                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12217         // don't do anything if there were no surfaces
12218         if (!numsurfacelist)
12219         {
12220                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12221                 return;
12222         }
12223         // update lightmaps if needed
12224         if (update)
12225         {
12226                 int updated = 0;
12227                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12228                 {
12229                         if (update[j])
12230                         {
12231                                 updated++;
12232                                 R_BuildLightMap(ent, surfaces + j);
12233                         }
12234                 }
12235         }
12236
12237         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12238
12239         // add to stats if desired
12240         if (r_speeds.integer && !skysurfaces && !depthonly)
12241         {
12242                 r_refdef.stats.entities_surfaces += numsurfacelist;
12243                 for (j = 0;j < numsurfacelist;j++)
12244                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12245         }
12246
12247         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12248 }
12249
12250 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12251 {
12252         static texture_t texture;
12253         static msurface_t surface;
12254         const msurface_t *surfacelist = &surface;
12255
12256         // fake enough texture and surface state to render this geometry
12257
12258         texture.update_lastrenderframe = -1; // regenerate this texture
12259         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12260         texture.currentskinframe = skinframe;
12261         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12262         texture.offsetmapping = OFFSETMAPPING_OFF;
12263         texture.offsetscale = 1;
12264         texture.specularscalemod = 1;
12265         texture.specularpowermod = 1;
12266         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12267         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12268         // JUST GREP FOR "specularscalemod = 1".
12269
12270         surface.texture = &texture;
12271         surface.num_triangles = numtriangles;
12272         surface.num_firsttriangle = firsttriangle;
12273         surface.num_vertices = numvertices;
12274         surface.num_firstvertex = firstvertex;
12275
12276         // now render it
12277         rsurface.texture = R_GetCurrentTexture(surface.texture);
12278         rsurface.lightmaptexture = NULL;
12279         rsurface.deluxemaptexture = NULL;
12280         rsurface.uselightmaptexture = false;
12281         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12282 }
12283
12284 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)
12285 {
12286         static msurface_t surface;
12287         const msurface_t *surfacelist = &surface;
12288
12289         // fake enough texture and surface state to render this geometry
12290         surface.texture = texture;
12291         surface.num_triangles = numtriangles;
12292         surface.num_firsttriangle = firsttriangle;
12293         surface.num_vertices = numvertices;
12294         surface.num_firstvertex = firstvertex;
12295
12296         // now render it
12297         rsurface.texture = R_GetCurrentTexture(surface.texture);
12298         rsurface.lightmaptexture = NULL;
12299         rsurface.deluxemaptexture = NULL;
12300         rsurface.uselightmaptexture = false;
12301         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12302 }