]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
implemented use of GL_ARB_uniform_buffer_object for r_glsl_skeletal
[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 static qboolean r_gpuskeletal;
48
49 //
50 // screen size info
51 //
52 r_refdef_t r_refdef;
53
54 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!"};
55 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!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 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)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 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"};
61 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"};
62 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"};
63 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"};
64 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"};
65 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"};
66
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 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"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 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)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72
73 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"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
85 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)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 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"};
89 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"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 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)"};
102 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)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
108
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
112
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 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."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 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."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 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."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 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"};
127 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"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 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"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 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
138 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
139
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
148
149 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)"};
150 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"};
151
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
155
156 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"};
157 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"};
158 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"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 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"};
162 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)"};
163 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)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
165
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 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)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 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)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 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)"};
172 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)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 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"};
175 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."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
184 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)"};
185
186 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)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 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"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 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"};
193 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"};
194 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)"};
195
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
200
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
203
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
210
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
221
222 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"};
223
224 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"};
225
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
227
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
229
230 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)"};
231 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)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233
234 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
235 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"};
236
237 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."};
238
239 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)"};
240 cvar_t r_bufferdatasize[R_BUFFERDATA_COUNT] =
241 {
242         {CVAR_SAVE, "r_bufferdatasize_vertex", "4", "vertex buffer size for one frame"},
243         {CVAR_SAVE, "r_bufferdatasize_index16", "1", "index buffer size for one frame (16bit indices)"},
244         {CVAR_SAVE, "r_bufferdatasize_index32", "1", "index buffer size for one frame (32bit indices)"},
245         {CVAR_SAVE, "r_bufferdatasize_uniform", "0.25", "uniform buffer size for one frame"},
246 };
247
248 extern cvar_t v_glslgamma;
249 extern cvar_t v_glslgamma_2d;
250
251 extern qboolean v_flipped_state;
252
253 r_framebufferstate_t r_fb;
254
255 /// shadow volume bsp struct with automatically growing nodes buffer
256 svbsp_t r_svbsp;
257
258 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
259
260 rtexture_t *r_texture_blanknormalmap;
261 rtexture_t *r_texture_white;
262 rtexture_t *r_texture_grey128;
263 rtexture_t *r_texture_black;
264 rtexture_t *r_texture_notexture;
265 rtexture_t *r_texture_whitecube;
266 rtexture_t *r_texture_normalizationcube;
267 rtexture_t *r_texture_fogattenuation;
268 rtexture_t *r_texture_fogheighttexture;
269 rtexture_t *r_texture_gammaramps;
270 unsigned int r_texture_gammaramps_serial;
271 //rtexture_t *r_texture_fogintensity;
272 rtexture_t *r_texture_reflectcube;
273
274 // TODO: hash lookups?
275 typedef struct cubemapinfo_s
276 {
277         char basename[64];
278         rtexture_t *texture;
279 }
280 cubemapinfo_t;
281
282 int r_texture_numcubemaps;
283 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
284
285 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
286 unsigned int r_numqueries;
287 unsigned int r_maxqueries;
288
289 typedef struct r_qwskincache_s
290 {
291         char name[MAX_QPATH];
292         skinframe_t *skinframe;
293 }
294 r_qwskincache_t;
295
296 static r_qwskincache_t *r_qwskincache;
297 static int r_qwskincache_size;
298
299 /// vertex coordinates for a quad that covers the screen exactly
300 extern const float r_screenvertex3f[12];
301 extern const float r_d3dscreenvertex3f[12];
302 const float r_screenvertex3f[12] =
303 {
304         0, 0, 0,
305         1, 0, 0,
306         1, 1, 0,
307         0, 1, 0
308 };
309 const float r_d3dscreenvertex3f[12] =
310 {
311         0, 1, 0,
312         1, 1, 0,
313         1, 0, 0,
314         0, 0, 0
315 };
316
317 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
318 {
319         int i;
320         for (i = 0;i < verts;i++)
321         {
322                 out[0] = in[0] * r;
323                 out[1] = in[1] * g;
324                 out[2] = in[2] * b;
325                 out[3] = in[3];
326                 in += 4;
327                 out += 4;
328         }
329 }
330
331 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
332 {
333         int i;
334         for (i = 0;i < verts;i++)
335         {
336                 out[0] = r;
337                 out[1] = g;
338                 out[2] = b;
339                 out[3] = a;
340                 out += 4;
341         }
342 }
343
344 // FIXME: move this to client?
345 void FOG_clear(void)
346 {
347         if (gamemode == GAME_NEHAHRA)
348         {
349                 Cvar_Set("gl_fogenable", "0");
350                 Cvar_Set("gl_fogdensity", "0.2");
351                 Cvar_Set("gl_fogred", "0.3");
352                 Cvar_Set("gl_foggreen", "0.3");
353                 Cvar_Set("gl_fogblue", "0.3");
354         }
355         r_refdef.fog_density = 0;
356         r_refdef.fog_red = 0;
357         r_refdef.fog_green = 0;
358         r_refdef.fog_blue = 0;
359         r_refdef.fog_alpha = 1;
360         r_refdef.fog_start = 0;
361         r_refdef.fog_end = 16384;
362         r_refdef.fog_height = 1<<30;
363         r_refdef.fog_fadedepth = 128;
364         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
365 }
366
367 static void R_BuildBlankTextures(void)
368 {
369         unsigned char data[4];
370         data[2] = 128; // normal X
371         data[1] = 128; // normal Y
372         data[0] = 255; // normal Z
373         data[3] = 255; // height
374         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 255;
376         data[1] = 255;
377         data[2] = 255;
378         data[3] = 255;
379         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 128;
381         data[1] = 128;
382         data[2] = 128;
383         data[3] = 255;
384         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 0;
386         data[1] = 0;
387         data[2] = 0;
388         data[3] = 255;
389         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 }
391
392 static void R_BuildNoTexture(void)
393 {
394         int x, y;
395         unsigned char pix[16][16][4];
396         // this makes a light grey/dark grey checkerboard texture
397         for (y = 0;y < 16;y++)
398         {
399                 for (x = 0;x < 16;x++)
400                 {
401                         if ((y < 8) ^ (x < 8))
402                         {
403                                 pix[y][x][0] = 128;
404                                 pix[y][x][1] = 128;
405                                 pix[y][x][2] = 128;
406                                 pix[y][x][3] = 255;
407                         }
408                         else
409                         {
410                                 pix[y][x][0] = 64;
411                                 pix[y][x][1] = 64;
412                                 pix[y][x][2] = 64;
413                                 pix[y][x][3] = 255;
414                         }
415                 }
416         }
417         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
418 }
419
420 static void R_BuildWhiteCube(void)
421 {
422         unsigned char data[6*1*1*4];
423         memset(data, 255, sizeof(data));
424         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
425 }
426
427 static void R_BuildNormalizationCube(void)
428 {
429         int x, y, side;
430         vec3_t v;
431         vec_t s, t, intensity;
432 #define NORMSIZE 64
433         unsigned char *data;
434         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
435         for (side = 0;side < 6;side++)
436         {
437                 for (y = 0;y < NORMSIZE;y++)
438                 {
439                         for (x = 0;x < NORMSIZE;x++)
440                         {
441                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
442                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 switch(side)
444                                 {
445                                 default:
446                                 case 0:
447                                         v[0] = 1;
448                                         v[1] = -t;
449                                         v[2] = -s;
450                                         break;
451                                 case 1:
452                                         v[0] = -1;
453                                         v[1] = -t;
454                                         v[2] = s;
455                                         break;
456                                 case 2:
457                                         v[0] = s;
458                                         v[1] = 1;
459                                         v[2] = t;
460                                         break;
461                                 case 3:
462                                         v[0] = s;
463                                         v[1] = -1;
464                                         v[2] = -t;
465                                         break;
466                                 case 4:
467                                         v[0] = s;
468                                         v[1] = -t;
469                                         v[2] = 1;
470                                         break;
471                                 case 5:
472                                         v[0] = -s;
473                                         v[1] = -t;
474                                         v[2] = -1;
475                                         break;
476                                 }
477                                 intensity = 127.0f / sqrt(DotProduct(v, v));
478                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
479                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
480                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
481                                 data[((side*64+y)*64+x)*4+3] = 255;
482                         }
483                 }
484         }
485         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
486         Mem_Free(data);
487 }
488
489 static void R_BuildFogTexture(void)
490 {
491         int x, b;
492 #define FOGWIDTH 256
493         unsigned char data1[FOGWIDTH][4];
494         //unsigned char data2[FOGWIDTH][4];
495         double d, r, alpha;
496
497         r_refdef.fogmasktable_start = r_refdef.fog_start;
498         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
499         r_refdef.fogmasktable_range = r_refdef.fogrange;
500         r_refdef.fogmasktable_density = r_refdef.fog_density;
501
502         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
503         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
504         {
505                 d = (x * r - r_refdef.fogmasktable_start);
506                 if(developer_extra.integer)
507                         Con_DPrintf("%f ", d);
508                 d = max(0, d);
509                 if (r_fog_exp2.integer)
510                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
511                 else
512                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
513                 if(developer_extra.integer)
514                         Con_DPrintf(" : %f ", alpha);
515                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
516                 if(developer_extra.integer)
517                         Con_DPrintf(" = %f\n", alpha);
518                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
519         }
520
521         for (x = 0;x < FOGWIDTH;x++)
522         {
523                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
524                 data1[x][0] = b;
525                 data1[x][1] = b;
526                 data1[x][2] = b;
527                 data1[x][3] = 255;
528                 //data2[x][0] = 255 - b;
529                 //data2[x][1] = 255 - b;
530                 //data2[x][2] = 255 - b;
531                 //data2[x][3] = 255;
532         }
533         if (r_texture_fogattenuation)
534         {
535                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
536                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537         }
538         else
539         {
540                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
541                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
542         }
543 }
544
545 static void R_BuildFogHeightTexture(void)
546 {
547         unsigned char *inpixels;
548         int size;
549         int x;
550         int y;
551         int j;
552         float c[4];
553         float f;
554         inpixels = NULL;
555         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
556         if (r_refdef.fogheighttexturename[0])
557                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
558         if (!inpixels)
559         {
560                 r_refdef.fog_height_tablesize = 0;
561                 if (r_texture_fogheighttexture)
562                         R_FreeTexture(r_texture_fogheighttexture);
563                 r_texture_fogheighttexture = NULL;
564                 if (r_refdef.fog_height_table2d)
565                         Mem_Free(r_refdef.fog_height_table2d);
566                 r_refdef.fog_height_table2d = NULL;
567                 if (r_refdef.fog_height_table1d)
568                         Mem_Free(r_refdef.fog_height_table1d);
569                 r_refdef.fog_height_table1d = NULL;
570                 return;
571         }
572         size = image_width;
573         r_refdef.fog_height_tablesize = size;
574         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
575         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
576         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
577         Mem_Free(inpixels);
578         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
579         // average fog color table accounting for every fog layer between a point
580         // and the camera.  (Note: attenuation is handled separately!)
581         for (y = 0;y < size;y++)
582         {
583                 for (x = 0;x < size;x++)
584                 {
585                         Vector4Clear(c);
586                         f = 0;
587                         if (x < y)
588                         {
589                                 for (j = x;j <= y;j++)
590                                 {
591                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592                                         f++;
593                                 }
594                         }
595                         else
596                         {
597                                 for (j = x;j >= y;j--)
598                                 {
599                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
600                                         f++;
601                                 }
602                         }
603                         f = 1.0f / f;
604                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
605                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
608                 }
609         }
610         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
611 }
612
613 //=======================================================================================================================================================
614
615 static const char *builtinshaderstrings[] =
616 {
617 #include "shader_glsl.h"
618 0
619 };
620
621 const char *builtinhlslshaderstrings[] =
622 {
623 #include "shader_hlsl.h"
624 0
625 };
626
627 char *glslshaderstring = NULL;
628 char *hlslshaderstring = NULL;
629
630 //=======================================================================================================================================================
631
632 typedef struct shaderpermutationinfo_s
633 {
634         const char *pretext;
635         const char *name;
636 }
637 shaderpermutationinfo_t;
638
639 typedef struct shadermodeinfo_s
640 {
641         const char *filename;
642         const char *pretext;
643         const char *name;
644 }
645 shadermodeinfo_t;
646
647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
649 {
650         {"#define USEDIFFUSE\n", " diffuse"},
651         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
652         {"#define USEVIEWTINT\n", " viewtint"},
653         {"#define USECOLORMAPPING\n", " colormapping"},
654         {"#define USESATURATION\n", " saturation"},
655         {"#define USEFOGINSIDE\n", " foginside"},
656         {"#define USEFOGOUTSIDE\n", " fogoutside"},
657         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
658         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
659         {"#define USEGAMMARAMPS\n", " gammaramps"},
660         {"#define USECUBEFILTER\n", " cubefilter"},
661         {"#define USEGLOW\n", " glow"},
662         {"#define USEBLOOM\n", " bloom"},
663         {"#define USESPECULAR\n", " specular"},
664         {"#define USEPOSTPROCESSING\n", " postprocessing"},
665         {"#define USEREFLECTION\n", " reflection"},
666         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
668         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
669         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
670         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
671         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
672         {"#define USEALPHAKILL\n", " alphakill"},
673         {"#define USEREFLECTCUBE\n", " reflectcube"},
674         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
675         {"#define USEBOUNCEGRID\n", " bouncegrid"},
676         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
677         {"#define USETRIPPY\n", " trippy"},
678         {"#define USEDEPTHRGB\n", " depthrgb"},
679         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
680         {"#define USESKELETAL\n", " skeletal"}
681 };
682
683 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
684 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
685 {
686         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
687         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
696         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
697         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
701         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
702         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 };
704
705 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
706 {
707         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
708         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
709         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
710         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
711         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
712         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
713         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
714         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
715         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
716         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
717         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
718         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
719         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
720         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
721         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
722         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
723         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
724 };
725
726 struct r_glsl_permutation_s;
727 typedef struct r_glsl_permutation_s
728 {
729         /// hash lookup data
730         struct r_glsl_permutation_s *hashnext;
731         unsigned int mode;
732         unsigned int permutation;
733
734         /// indicates if we have tried compiling this permutation already
735         qboolean compiled;
736         /// 0 if compilation failed
737         int program;
738         // texture units assigned to each detected uniform
739         int tex_Texture_First;
740         int tex_Texture_Second;
741         int tex_Texture_GammaRamps;
742         int tex_Texture_Normal;
743         int tex_Texture_Color;
744         int tex_Texture_Gloss;
745         int tex_Texture_Glow;
746         int tex_Texture_SecondaryNormal;
747         int tex_Texture_SecondaryColor;
748         int tex_Texture_SecondaryGloss;
749         int tex_Texture_SecondaryGlow;
750         int tex_Texture_Pants;
751         int tex_Texture_Shirt;
752         int tex_Texture_FogHeightTexture;
753         int tex_Texture_FogMask;
754         int tex_Texture_Lightmap;
755         int tex_Texture_Deluxemap;
756         int tex_Texture_Attenuation;
757         int tex_Texture_Cube;
758         int tex_Texture_Refraction;
759         int tex_Texture_Reflection;
760         int tex_Texture_ShadowMap2D;
761         int tex_Texture_CubeProjection;
762         int tex_Texture_ScreenNormalMap;
763         int tex_Texture_ScreenDiffuse;
764         int tex_Texture_ScreenSpecular;
765         int tex_Texture_ReflectMask;
766         int tex_Texture_ReflectCube;
767         int tex_Texture_BounceGrid;
768         /// locations of detected uniforms in program object, or -1 if not found
769         int loc_Texture_First;
770         int loc_Texture_Second;
771         int loc_Texture_GammaRamps;
772         int loc_Texture_Normal;
773         int loc_Texture_Color;
774         int loc_Texture_Gloss;
775         int loc_Texture_Glow;
776         int loc_Texture_SecondaryNormal;
777         int loc_Texture_SecondaryColor;
778         int loc_Texture_SecondaryGloss;
779         int loc_Texture_SecondaryGlow;
780         int loc_Texture_Pants;
781         int loc_Texture_Shirt;
782         int loc_Texture_FogHeightTexture;
783         int loc_Texture_FogMask;
784         int loc_Texture_Lightmap;
785         int loc_Texture_Deluxemap;
786         int loc_Texture_Attenuation;
787         int loc_Texture_Cube;
788         int loc_Texture_Refraction;
789         int loc_Texture_Reflection;
790         int loc_Texture_ShadowMap2D;
791         int loc_Texture_CubeProjection;
792         int loc_Texture_ScreenNormalMap;
793         int loc_Texture_ScreenDiffuse;
794         int loc_Texture_ScreenSpecular;
795         int loc_Texture_ReflectMask;
796         int loc_Texture_ReflectCube;
797         int loc_Texture_BounceGrid;
798         int loc_Alpha;
799         int loc_BloomBlur_Parameters;
800         int loc_ClientTime;
801         int loc_Color_Ambient;
802         int loc_Color_Diffuse;
803         int loc_Color_Specular;
804         int loc_Color_Glow;
805         int loc_Color_Pants;
806         int loc_Color_Shirt;
807         int loc_DeferredColor_Ambient;
808         int loc_DeferredColor_Diffuse;
809         int loc_DeferredColor_Specular;
810         int loc_DeferredMod_Diffuse;
811         int loc_DeferredMod_Specular;
812         int loc_DistortScaleRefractReflect;
813         int loc_EyePosition;
814         int loc_FogColor;
815         int loc_FogHeightFade;
816         int loc_FogPlane;
817         int loc_FogPlaneViewDist;
818         int loc_FogRangeRecip;
819         int loc_LightColor;
820         int loc_LightDir;
821         int loc_LightPosition;
822         int loc_OffsetMapping_ScaleSteps;
823         int loc_OffsetMapping_LodDistance;
824         int loc_OffsetMapping_Bias;
825         int loc_PixelSize;
826         int loc_ReflectColor;
827         int loc_ReflectFactor;
828         int loc_ReflectOffset;
829         int loc_RefractColor;
830         int loc_Saturation;
831         int loc_ScreenCenterRefractReflect;
832         int loc_ScreenScaleRefractReflect;
833         int loc_ScreenToDepth;
834         int loc_ShadowMap_Parameters;
835         int loc_ShadowMap_TextureScale;
836         int loc_SpecularPower;
837         int loc_Skeletal_Transform12;
838         int loc_UserVec1;
839         int loc_UserVec2;
840         int loc_UserVec3;
841         int loc_UserVec4;
842         int loc_ViewTintColor;
843         int loc_ViewToLight;
844         int loc_ModelToLight;
845         int loc_TexMatrix;
846         int loc_BackgroundTexMatrix;
847         int loc_ModelViewProjectionMatrix;
848         int loc_ModelViewMatrix;
849         int loc_PixelToScreenTexCoord;
850         int loc_ModelToReflectCube;
851         int loc_ShadowMapMatrix;
852         int loc_BloomColorSubtract;
853         int loc_NormalmapScrollBlend;
854         int loc_BounceGridMatrix;
855         int loc_BounceGridIntensity;
856         /// uniform block bindings
857         int ubibind_Skeletal_Transform12_UniformBlock;
858         /// uniform block indices
859         int ubiloc_Skeletal_Transform12_UniformBlock;
860 }
861 r_glsl_permutation_t;
862
863 #define SHADERPERMUTATION_HASHSIZE 256
864
865
866 // non-degradable "lightweight" shader parameters to keep the permutations simpler
867 // these can NOT degrade! only use for simple stuff
868 enum
869 {
870         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
871         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
872         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
873         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
876         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
877         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
878         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
879         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
880         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
881         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
882         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
883 };
884 #define SHADERSTATICPARMS_COUNT 13
885
886 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
887 static int shaderstaticparms_count = 0;
888
889 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
890 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
891
892 extern qboolean r_shadow_shadowmapsampler;
893 extern int r_shadow_shadowmappcf;
894 qboolean R_CompileShader_CheckStaticParms(void)
895 {
896         static int r_compileshader_staticparms_save[1];
897         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
898         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
899
900         // detect all
901         if (r_glsl_saturation_redcompensate.integer)
902                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
903         if (r_glsl_vertextextureblend_usebothalphas.integer)
904                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
905         if (r_shadow_glossexact.integer)
906                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
907         if (r_glsl_postprocess.integer)
908         {
909                 if (r_glsl_postprocess_uservec1_enable.integer)
910                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
911                 if (r_glsl_postprocess_uservec2_enable.integer)
912                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
913                 if (r_glsl_postprocess_uservec3_enable.integer)
914                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
915                 if (r_glsl_postprocess_uservec4_enable.integer)
916                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
917         }
918         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
919                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
920
921         if (r_shadow_shadowmapsampler)
922                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
923         if (r_shadow_shadowmappcf > 1)
924                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
925         else if (r_shadow_shadowmappcf)
926                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
927         if (r_celshading.integer)
928                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
929         if (r_celoutlines.integer)
930                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
931
932         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
933 }
934
935 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
936         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
937                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
938         else \
939                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
940 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
941 {
942         shaderstaticparms_count = 0;
943
944         // emit all
945         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
946         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
947         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
948         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
949         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
950         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
951         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
952         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
953         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
954         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
955         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
956         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
957         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
958 }
959
960 /// information about each possible shader permutation
961 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
962 /// currently selected permutation
963 r_glsl_permutation_t *r_glsl_permutation;
964 /// storage for permutations linked in the hash table
965 memexpandablearray_t r_glsl_permutationarray;
966
967 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
968 {
969         //unsigned int hashdepth = 0;
970         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
971         r_glsl_permutation_t *p;
972         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
973         {
974                 if (p->mode == mode && p->permutation == permutation)
975                 {
976                         //if (hashdepth > 10)
977                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
978                         return p;
979                 }
980                 //hashdepth++;
981         }
982         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
983         p->mode = mode;
984         p->permutation = permutation;
985         p->hashnext = r_glsl_permutationhash[mode][hashindex];
986         r_glsl_permutationhash[mode][hashindex] = p;
987         //if (hashdepth > 10)
988         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
989         return p;
990 }
991
992 static char *R_ShaderStrCat(const char **strings)
993 {
994         char *string, *s;
995         const char **p = strings;
996         const char *t;
997         size_t len = 0;
998         for (p = strings;(t = *p);p++)
999                 len += strlen(t);
1000         len++;
1001         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1002         len = 0;
1003         for (p = strings;(t = *p);p++)
1004         {
1005                 len = strlen(t);
1006                 memcpy(s, t, len);
1007                 s += len;
1008         }
1009         *s = 0;
1010         return string;
1011 }
1012
1013 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1014 {
1015         char *shaderstring;
1016         if (!filename || !filename[0])
1017                 return NULL;
1018         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1019         if (!strcmp(filename, "glsl/default.glsl"))
1020         {
1021                 if (builtinonly)
1022                         return R_ShaderStrCat(builtinshaderstrings);
1023                 if (!glslshaderstring)
1024                 {
1025                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1026                         if (glslshaderstring)
1027                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1028                         else
1029                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1030                 }
1031                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1032                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1033                 return shaderstring;
1034         }
1035         if (!strcmp(filename, "hlsl/default.hlsl"))
1036         {
1037                 if (builtinonly)
1038                         return R_ShaderStrCat(builtinhlslshaderstrings);
1039                 if (!hlslshaderstring)
1040                 {
1041                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1042                         if (hlslshaderstring)
1043                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1044                         else
1045                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1046                 }
1047                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1048                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1049                 return shaderstring;
1050         }
1051         // we don't have builtin strings for any other files
1052         if (builtinonly)
1053                 return NULL;
1054         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1055         if (shaderstring)
1056         {
1057                 if (printfromdisknotice)
1058                         Con_DPrintf("from disk %s... ", filename);
1059                 return shaderstring;
1060         }
1061         return shaderstring;
1062 }
1063
1064 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1065 {
1066         int i;
1067         int ubibind;
1068         int sampler;
1069         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1070         char *sourcestring;
1071         char permutationname[256];
1072         int vertstrings_count = 0;
1073         int geomstrings_count = 0;
1074         int fragstrings_count = 0;
1075         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1076         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078
1079         if (p->compiled)
1080                 return;
1081         p->compiled = true;
1082         p->program = 0;
1083
1084         permutationname[0] = 0;
1085         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1086
1087         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1088
1089         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1090         if(vid.support.glshaderversion >= 140)
1091         {
1092                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1093                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1094                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1095                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1096                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1097                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1098         }
1099         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1100         else if(vid.support.glshaderversion >= 130)
1101         {
1102                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1103                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1104                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1105                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1106                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1107                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1108         }
1109
1110         // the first pretext is which type of shader to compile as
1111         // (later these will all be bound together as a program object)
1112         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1113         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1114         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1115
1116         // the second pretext is the mode (for example a light source)
1117         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1118         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1119         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1120         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1121
1122         // now add all the permutation pretexts
1123         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1124         {
1125                 if (permutation & (1<<i))
1126                 {
1127                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1128                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1129                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1130                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1131                 }
1132                 else
1133                 {
1134                         // keep line numbers correct
1135                         vertstrings_list[vertstrings_count++] = "\n";
1136                         geomstrings_list[geomstrings_count++] = "\n";
1137                         fragstrings_list[fragstrings_count++] = "\n";
1138                 }
1139         }
1140
1141         // add static parms
1142         R_CompileShader_AddStaticParms(mode, permutation);
1143         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1144         vertstrings_count += shaderstaticparms_count;
1145         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1146         geomstrings_count += shaderstaticparms_count;
1147         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1148         fragstrings_count += shaderstaticparms_count;
1149
1150         // now append the shader text itself
1151         vertstrings_list[vertstrings_count++] = sourcestring;
1152         geomstrings_list[geomstrings_count++] = sourcestring;
1153         fragstrings_list[fragstrings_count++] = sourcestring;
1154
1155         // compile the shader program
1156         if (vertstrings_count + geomstrings_count + fragstrings_count)
1157                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1158         if (p->program)
1159         {
1160                 CHECKGLERROR
1161                 qglUseProgram(p->program);CHECKGLERROR
1162                 // look up all the uniform variable names we care about, so we don't
1163                 // have to look them up every time we set them
1164
1165                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1166                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1167                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1168                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1169                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1170                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1171                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1172                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1173                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1174                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1175                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1176                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1177                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1178                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1179                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1180                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1181                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1182                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1183                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1184                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1185                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1186                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1187                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1188                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1189                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1190                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1191                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1192                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1193                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1194                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1195                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1196                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1197                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1198                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1199                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1200                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1201                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1202                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1203                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1204                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1205                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1206                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1207                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1208                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1209                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1210                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1211                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1212                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1213                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1214                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1215                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1216                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1217                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1218                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1219                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1220                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1221                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1222                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1223                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1224                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1225                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1226                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1227                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1228                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1229                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1230                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1231                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1232                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1233                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1234                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1235                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1236                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1237                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1238                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1239                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1240                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1241                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1242                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1243                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1244                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1245                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1246                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1247                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1248                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1249                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1250                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1251                 // initialize the samplers to refer to the texture units we use
1252                 p->tex_Texture_First = -1;
1253                 p->tex_Texture_Second = -1;
1254                 p->tex_Texture_GammaRamps = -1;
1255                 p->tex_Texture_Normal = -1;
1256                 p->tex_Texture_Color = -1;
1257                 p->tex_Texture_Gloss = -1;
1258                 p->tex_Texture_Glow = -1;
1259                 p->tex_Texture_SecondaryNormal = -1;
1260                 p->tex_Texture_SecondaryColor = -1;
1261                 p->tex_Texture_SecondaryGloss = -1;
1262                 p->tex_Texture_SecondaryGlow = -1;
1263                 p->tex_Texture_Pants = -1;
1264                 p->tex_Texture_Shirt = -1;
1265                 p->tex_Texture_FogHeightTexture = -1;
1266                 p->tex_Texture_FogMask = -1;
1267                 p->tex_Texture_Lightmap = -1;
1268                 p->tex_Texture_Deluxemap = -1;
1269                 p->tex_Texture_Attenuation = -1;
1270                 p->tex_Texture_Cube = -1;
1271                 p->tex_Texture_Refraction = -1;
1272                 p->tex_Texture_Reflection = -1;
1273                 p->tex_Texture_ShadowMap2D = -1;
1274                 p->tex_Texture_CubeProjection = -1;
1275                 p->tex_Texture_ScreenNormalMap = -1;
1276                 p->tex_Texture_ScreenDiffuse = -1;
1277                 p->tex_Texture_ScreenSpecular = -1;
1278                 p->tex_Texture_ReflectMask = -1;
1279                 p->tex_Texture_ReflectCube = -1;
1280                 p->tex_Texture_BounceGrid = -1;
1281                 // bind the texture samplers in use
1282                 sampler = 0;
1283                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1284                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1285                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1286                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1287                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1288                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1289                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1290                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1291                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1292                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1293                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1294                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1295                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1296                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1297                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1298                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1299                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1300                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1301                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1302                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1303                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1304                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1305                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1306                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1307                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1308                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1309                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1310                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1311                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1312                 // get the uniform block indices so we can bind them
1313                 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1314                 // clear the uniform block bindings
1315                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1316                 // bind the uniform blocks in use
1317                 ubibind = 0;
1318                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1319                 // we're done compiling and setting up the shader, at least until it is used
1320                 CHECKGLERROR
1321                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1322         }
1323         else
1324                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1325
1326         // free the strings
1327         if (sourcestring)
1328                 Mem_Free(sourcestring);
1329 }
1330
1331 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1332 {
1333         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1334         if (r_glsl_permutation != perm)
1335         {
1336                 r_glsl_permutation = perm;
1337                 if (!r_glsl_permutation->program)
1338                 {
1339                         if (!r_glsl_permutation->compiled)
1340                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1341                         if (!r_glsl_permutation->program)
1342                         {
1343                                 // remove features until we find a valid permutation
1344                                 int i;
1345                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1346                                 {
1347                                         // reduce i more quickly whenever it would not remove any bits
1348                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1349                                         if (!(permutation & j))
1350                                                 continue;
1351                                         permutation -= j;
1352                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1353                                         if (!r_glsl_permutation->compiled)
1354                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1355                                         if (r_glsl_permutation->program)
1356                                                 break;
1357                                 }
1358                                 if (i >= SHADERPERMUTATION_COUNT)
1359                                 {
1360                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1361                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1362                                         qglUseProgram(0);CHECKGLERROR
1363                                         return; // no bit left to clear, entire mode is broken
1364                                 }
1365                         }
1366                 }
1367                 CHECKGLERROR
1368                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1369         }
1370         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1371         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1372         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1373 }
1374
1375 #ifdef SUPPORTD3D
1376
1377 #ifdef SUPPORTD3D
1378 #include <d3d9.h>
1379 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1380 extern D3DCAPS9 vid_d3d9caps;
1381 #endif
1382
1383 struct r_hlsl_permutation_s;
1384 typedef struct r_hlsl_permutation_s
1385 {
1386         /// hash lookup data
1387         struct r_hlsl_permutation_s *hashnext;
1388         unsigned int mode;
1389         unsigned int permutation;
1390
1391         /// indicates if we have tried compiling this permutation already
1392         qboolean compiled;
1393         /// NULL if compilation failed
1394         IDirect3DVertexShader9 *vertexshader;
1395         IDirect3DPixelShader9 *pixelshader;
1396 }
1397 r_hlsl_permutation_t;
1398
1399 typedef enum D3DVSREGISTER_e
1400 {
1401         D3DVSREGISTER_TexMatrix = 0, // float4x4
1402         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1403         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1404         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1405         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1406         D3DVSREGISTER_ModelToLight = 20, // float4x4
1407         D3DVSREGISTER_EyePosition = 24,
1408         D3DVSREGISTER_FogPlane = 25,
1409         D3DVSREGISTER_LightDir = 26,
1410         D3DVSREGISTER_LightPosition = 27,
1411 }
1412 D3DVSREGISTER_t;
1413
1414 typedef enum D3DPSREGISTER_e
1415 {
1416         D3DPSREGISTER_Alpha = 0,
1417         D3DPSREGISTER_BloomBlur_Parameters = 1,
1418         D3DPSREGISTER_ClientTime = 2,
1419         D3DPSREGISTER_Color_Ambient = 3,
1420         D3DPSREGISTER_Color_Diffuse = 4,
1421         D3DPSREGISTER_Color_Specular = 5,
1422         D3DPSREGISTER_Color_Glow = 6,
1423         D3DPSREGISTER_Color_Pants = 7,
1424         D3DPSREGISTER_Color_Shirt = 8,
1425         D3DPSREGISTER_DeferredColor_Ambient = 9,
1426         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1427         D3DPSREGISTER_DeferredColor_Specular = 11,
1428         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1429         D3DPSREGISTER_DeferredMod_Specular = 13,
1430         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1431         D3DPSREGISTER_EyePosition = 15, // unused
1432         D3DPSREGISTER_FogColor = 16,
1433         D3DPSREGISTER_FogHeightFade = 17,
1434         D3DPSREGISTER_FogPlane = 18,
1435         D3DPSREGISTER_FogPlaneViewDist = 19,
1436         D3DPSREGISTER_FogRangeRecip = 20,
1437         D3DPSREGISTER_LightColor = 21,
1438         D3DPSREGISTER_LightDir = 22, // unused
1439         D3DPSREGISTER_LightPosition = 23,
1440         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1441         D3DPSREGISTER_PixelSize = 25,
1442         D3DPSREGISTER_ReflectColor = 26,
1443         D3DPSREGISTER_ReflectFactor = 27,
1444         D3DPSREGISTER_ReflectOffset = 28,
1445         D3DPSREGISTER_RefractColor = 29,
1446         D3DPSREGISTER_Saturation = 30,
1447         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1448         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1449         D3DPSREGISTER_ScreenToDepth = 33,
1450         D3DPSREGISTER_ShadowMap_Parameters = 34,
1451         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1452         D3DPSREGISTER_SpecularPower = 36,
1453         D3DPSREGISTER_UserVec1 = 37,
1454         D3DPSREGISTER_UserVec2 = 38,
1455         D3DPSREGISTER_UserVec3 = 39,
1456         D3DPSREGISTER_UserVec4 = 40,
1457         D3DPSREGISTER_ViewTintColor = 41,
1458         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1459         D3DPSREGISTER_BloomColorSubtract = 43,
1460         D3DPSREGISTER_ViewToLight = 44, // float4x4
1461         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1462         D3DPSREGISTER_NormalmapScrollBlend = 52,
1463         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1464         D3DPSREGISTER_OffsetMapping_Bias = 54,
1465         // next at 54
1466 }
1467 D3DPSREGISTER_t;
1468
1469 /// information about each possible shader permutation
1470 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1471 /// currently selected permutation
1472 r_hlsl_permutation_t *r_hlsl_permutation;
1473 /// storage for permutations linked in the hash table
1474 memexpandablearray_t r_hlsl_permutationarray;
1475
1476 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1477 {
1478         //unsigned int hashdepth = 0;
1479         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1480         r_hlsl_permutation_t *p;
1481         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1482         {
1483                 if (p->mode == mode && p->permutation == permutation)
1484                 {
1485                         //if (hashdepth > 10)
1486                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1487                         return p;
1488                 }
1489                 //hashdepth++;
1490         }
1491         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1492         p->mode = mode;
1493         p->permutation = permutation;
1494         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1495         r_hlsl_permutationhash[mode][hashindex] = p;
1496         //if (hashdepth > 10)
1497         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1498         return p;
1499 }
1500
1501 #include <d3dx9.h>
1502 //#include <d3dx9shader.h>
1503 //#include <d3dx9mesh.h>
1504
1505 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1506 {
1507         DWORD *vsbin = NULL;
1508         DWORD *psbin = NULL;
1509         fs_offset_t vsbinsize;
1510         fs_offset_t psbinsize;
1511 //      IDirect3DVertexShader9 *vs = NULL;
1512 //      IDirect3DPixelShader9 *ps = NULL;
1513         ID3DXBuffer *vslog = NULL;
1514         ID3DXBuffer *vsbuffer = NULL;
1515         ID3DXConstantTable *vsconstanttable = NULL;
1516         ID3DXBuffer *pslog = NULL;
1517         ID3DXBuffer *psbuffer = NULL;
1518         ID3DXConstantTable *psconstanttable = NULL;
1519         int vsresult = 0;
1520         int psresult = 0;
1521         char temp[MAX_INPUTLINE];
1522         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1523         char vabuf[1024];
1524         qboolean debugshader = gl_paranoid.integer != 0;
1525         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1526         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1527         if (!debugshader)
1528         {
1529                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1530                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1531         }
1532         if ((!vsbin && vertstring) || (!psbin && fragstring))
1533         {
1534                 const char* dllnames_d3dx9 [] =
1535                 {
1536                         "d3dx9_43.dll",
1537                         "d3dx9_42.dll",
1538                         "d3dx9_41.dll",
1539                         "d3dx9_40.dll",
1540                         "d3dx9_39.dll",
1541                         "d3dx9_38.dll",
1542                         "d3dx9_37.dll",
1543                         "d3dx9_36.dll",
1544                         "d3dx9_35.dll",
1545                         "d3dx9_34.dll",
1546                         "d3dx9_33.dll",
1547                         "d3dx9_32.dll",
1548                         "d3dx9_31.dll",
1549                         "d3dx9_30.dll",
1550                         "d3dx9_29.dll",
1551                         "d3dx9_28.dll",
1552                         "d3dx9_27.dll",
1553                         "d3dx9_26.dll",
1554                         "d3dx9_25.dll",
1555                         "d3dx9_24.dll",
1556                         NULL
1557                 };
1558                 dllhandle_t d3dx9_dll = NULL;
1559                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1560                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1561                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1562                 dllfunction_t d3dx9_dllfuncs[] =
1563                 {
1564                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1565                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1566                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1567                         {NULL, NULL}
1568                 };
1569                 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1570 #ifndef ID3DXBuffer_GetBufferPointer
1571 #if !defined(__cplusplus) || defined(CINTERFACE)
1572 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1573 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1574 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1575 #else
1576 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1577 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1578 #define ID3DXBuffer_Release(p)            (p)->Release()
1579 #endif
1580 #endif
1581                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1582                 {
1583                         DWORD shaderflags = 0;
1584                         if (debugshader)
1585                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1586                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1587                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1588                         if (vertstring && vertstring[0])
1589                         {
1590                                 if (debugshader)
1591                                 {
1592                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1593                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1594                                 }
1595                                 else
1596                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1597                                 if (vsbuffer)
1598                                 {
1599                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1600                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1601                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1602                                         ID3DXBuffer_Release(vsbuffer);
1603                                 }
1604                                 if (vslog)
1605                                 {
1606                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1607                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1608                                         ID3DXBuffer_Release(vslog);
1609                                 }
1610                         }
1611                         if (fragstring && fragstring[0])
1612                         {
1613                                 if (debugshader)
1614                                 {
1615                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1616                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1617                                 }
1618                                 else
1619                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1620                                 if (psbuffer)
1621                                 {
1622                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1623                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1624                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1625                                         ID3DXBuffer_Release(psbuffer);
1626                                 }
1627                                 if (pslog)
1628                                 {
1629                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1630                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1631                                         ID3DXBuffer_Release(pslog);
1632                                 }
1633                         }
1634                         Sys_UnloadLibrary(&d3dx9_dll);
1635                 }
1636                 else
1637                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1638         }
1639         if (vsbin && psbin)
1640         {
1641                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1642                 if (FAILED(vsresult))
1643                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1644                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1645                 if (FAILED(psresult))
1646                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1647         }
1648         // free the shader data
1649         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1650         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1651 }
1652
1653 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1654 {
1655         int i;
1656         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1657         int vertstring_length = 0;
1658         int geomstring_length = 0;
1659         int fragstring_length = 0;
1660         char *t;
1661         char *sourcestring;
1662         char *vertstring, *geomstring, *fragstring;
1663         char permutationname[256];
1664         char cachename[256];
1665         int vertstrings_count = 0;
1666         int geomstrings_count = 0;
1667         int fragstrings_count = 0;
1668         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1669         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1670         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1671
1672         if (p->compiled)
1673                 return;
1674         p->compiled = true;
1675         p->vertexshader = NULL;
1676         p->pixelshader = NULL;
1677
1678         permutationname[0] = 0;
1679         cachename[0] = 0;
1680         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1681
1682         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1683         strlcat(cachename, "hlsl/", sizeof(cachename));
1684
1685         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1686         vertstrings_count = 0;
1687         geomstrings_count = 0;
1688         fragstrings_count = 0;
1689         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1690         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1691         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1692
1693         // the first pretext is which type of shader to compile as
1694         // (later these will all be bound together as a program object)
1695         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1696         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1697         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1698
1699         // the second pretext is the mode (for example a light source)
1700         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1701         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1702         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1703         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1704         strlcat(cachename, modeinfo->name, sizeof(cachename));
1705
1706         // now add all the permutation pretexts
1707         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1708         {
1709                 if (permutation & (1<<i))
1710                 {
1711                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1712                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1713                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1714                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1715                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1716                 }
1717                 else
1718                 {
1719                         // keep line numbers correct
1720                         vertstrings_list[vertstrings_count++] = "\n";
1721                         geomstrings_list[geomstrings_count++] = "\n";
1722                         fragstrings_list[fragstrings_count++] = "\n";
1723                 }
1724         }
1725
1726         // add static parms
1727         R_CompileShader_AddStaticParms(mode, permutation);
1728         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1729         vertstrings_count += shaderstaticparms_count;
1730         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1731         geomstrings_count += shaderstaticparms_count;
1732         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1733         fragstrings_count += shaderstaticparms_count;
1734
1735         // replace spaces in the cachename with _ characters
1736         for (i = 0;cachename[i];i++)
1737                 if (cachename[i] == ' ')
1738                         cachename[i] = '_';
1739
1740         // now append the shader text itself
1741         vertstrings_list[vertstrings_count++] = sourcestring;
1742         geomstrings_list[geomstrings_count++] = sourcestring;
1743         fragstrings_list[fragstrings_count++] = sourcestring;
1744
1745         vertstring_length = 0;
1746         for (i = 0;i < vertstrings_count;i++)
1747                 vertstring_length += strlen(vertstrings_list[i]);
1748         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1749         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1750                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1751
1752         geomstring_length = 0;
1753         for (i = 0;i < geomstrings_count;i++)
1754                 geomstring_length += strlen(geomstrings_list[i]);
1755         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1756         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1757                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1758
1759         fragstring_length = 0;
1760         for (i = 0;i < fragstrings_count;i++)
1761                 fragstring_length += strlen(fragstrings_list[i]);
1762         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1763         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1764                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1765
1766         // try to load the cached shader, or generate one
1767         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1768
1769         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1770                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1771         else
1772                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1773
1774         // free the strings
1775         if (vertstring)
1776                 Mem_Free(vertstring);
1777         if (geomstring)
1778                 Mem_Free(geomstring);
1779         if (fragstring)
1780                 Mem_Free(fragstring);
1781         if (sourcestring)
1782                 Mem_Free(sourcestring);
1783 }
1784
1785 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1786 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1787 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);}
1788 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);}
1789 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);}
1790 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);}
1791
1792 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1793 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1794 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);}
1795 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);}
1796 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);}
1797 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);}
1798
1799 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1800 {
1801         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1802         if (r_hlsl_permutation != perm)
1803         {
1804                 r_hlsl_permutation = perm;
1805                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1806                 {
1807                         if (!r_hlsl_permutation->compiled)
1808                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1809                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1810                         {
1811                                 // remove features until we find a valid permutation
1812                                 int i;
1813                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1814                                 {
1815                                         // reduce i more quickly whenever it would not remove any bits
1816                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1817                                         if (!(permutation & j))
1818                                                 continue;
1819                                         permutation -= j;
1820                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1821                                         if (!r_hlsl_permutation->compiled)
1822                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1823                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1824                                                 break;
1825                                 }
1826                                 if (i >= SHADERPERMUTATION_COUNT)
1827                                 {
1828                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1829                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1830                                         return; // no bit left to clear, entire mode is broken
1831                                 }
1832                         }
1833                 }
1834                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1835                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1836         }
1837         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1838         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1839         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1840 }
1841 #endif
1842
1843 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1844 {
1845         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1846         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1847         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1848         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1849 }
1850
1851 void R_GLSL_Restart_f(void)
1852 {
1853         unsigned int i, limit;
1854         if (glslshaderstring)
1855                 Mem_Free(glslshaderstring);
1856         glslshaderstring = NULL;
1857         if (hlslshaderstring)
1858                 Mem_Free(hlslshaderstring);
1859         hlslshaderstring = NULL;
1860         switch(vid.renderpath)
1861         {
1862         case RENDERPATH_D3D9:
1863 #ifdef SUPPORTD3D
1864                 {
1865                         r_hlsl_permutation_t *p;
1866                         r_hlsl_permutation = NULL;
1867                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1868                         for (i = 0;i < limit;i++)
1869                         {
1870                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1871                                 {
1872                                         if (p->vertexshader)
1873                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1874                                         if (p->pixelshader)
1875                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1876                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1877                                 }
1878                         }
1879                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1880                 }
1881 #endif
1882                 break;
1883         case RENDERPATH_D3D10:
1884                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1885                 break;
1886         case RENDERPATH_D3D11:
1887                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1888                 break;
1889         case RENDERPATH_GL20:
1890         case RENDERPATH_GLES2:
1891                 {
1892                         r_glsl_permutation_t *p;
1893                         r_glsl_permutation = NULL;
1894                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1895                         for (i = 0;i < limit;i++)
1896                         {
1897                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1898                                 {
1899                                         GL_Backend_FreeProgram(p->program);
1900                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1901                                 }
1902                         }
1903                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1904                 }
1905                 break;
1906         case RENDERPATH_GL11:
1907         case RENDERPATH_GL13:
1908         case RENDERPATH_GLES1:
1909                 break;
1910         case RENDERPATH_SOFT:
1911                 break;
1912         }
1913 }
1914
1915 static void R_GLSL_DumpShader_f(void)
1916 {
1917         int i, language, mode, dupe;
1918         char *text;
1919         shadermodeinfo_t *modeinfo;
1920         qfile_t *file;
1921
1922         for (language = 0;language < 2;language++)
1923         {
1924                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1925                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1926                 {
1927                         // don't dump the same file multiple times (most or all shaders come from the same file)
1928                         for (dupe = mode - 1;dupe >= 0;dupe--)
1929                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1930                                         break;
1931                         if (dupe >= 0)
1932                                 continue;
1933                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1934                         if (!text)
1935                                 continue;
1936                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1937                         if (file)
1938                         {
1939                                 FS_Print(file, "/* The engine may define the following macros:\n");
1940                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1941                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1942                                         FS_Print(file, modeinfo[i].pretext);
1943                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1944                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1945                                 FS_Print(file, "*/\n");
1946                                 FS_Print(file, text);
1947                                 FS_Close(file);
1948                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1949                         }
1950                         else
1951                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1952                         Mem_Free(text);
1953                 }
1954         }
1955 }
1956
1957 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1958 {
1959         unsigned int permutation = 0;
1960         if (r_trippy.integer && !notrippy)
1961                 permutation |= SHADERPERMUTATION_TRIPPY;
1962         permutation |= SHADERPERMUTATION_VIEWTINT;
1963         if (first)
1964                 permutation |= SHADERPERMUTATION_DIFFUSE;
1965         if (second)
1966                 permutation |= SHADERPERMUTATION_SPECULAR;
1967         if (texturemode == GL_MODULATE)
1968                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1969         else if (texturemode == GL_ADD)
1970                 permutation |= SHADERPERMUTATION_GLOW;
1971         else if (texturemode == GL_DECAL)
1972                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1973         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1974                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1975         if (suppresstexalpha)
1976                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1977         if (!second)
1978                 texturemode = GL_MODULATE;
1979         if (vid.allowalphatocoverage)
1980                 GL_AlphaToCoverage(false);
1981         switch (vid.renderpath)
1982         {
1983         case RENDERPATH_D3D9:
1984 #ifdef SUPPORTD3D
1985                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1986                 R_Mesh_TexBind(GL20TU_FIRST , first );
1987                 R_Mesh_TexBind(GL20TU_SECOND, second);
1988                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1989                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1990 #endif
1991                 break;
1992         case RENDERPATH_D3D10:
1993                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1994                 break;
1995         case RENDERPATH_D3D11:
1996                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1997                 break;
1998         case RENDERPATH_GL20:
1999         case RENDERPATH_GLES2:
2000                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2001                 if (r_glsl_permutation->tex_Texture_First >= 0)
2002                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2003                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2004                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2005                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2006                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2007                 break;
2008         case RENDERPATH_GL13:
2009         case RENDERPATH_GLES1:
2010                 R_Mesh_TexBind(0, first );
2011                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2012                 R_Mesh_TexMatrix(0, NULL);
2013                 R_Mesh_TexBind(1, second);
2014                 if (second)
2015                 {
2016                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2017                         R_Mesh_TexMatrix(1, NULL);
2018                 }
2019                 break;
2020         case RENDERPATH_GL11:
2021                 R_Mesh_TexBind(0, first );
2022                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2023                 R_Mesh_TexMatrix(0, NULL);
2024                 break;
2025         case RENDERPATH_SOFT:
2026                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2027                 R_Mesh_TexBind(GL20TU_FIRST , first );
2028                 R_Mesh_TexBind(GL20TU_SECOND, second);
2029                 break;
2030         }
2031 }
2032
2033 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2034 {
2035         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2036 }
2037
2038 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2039 {
2040         unsigned int permutation = 0;
2041         if (r_trippy.integer && !notrippy)
2042                 permutation |= SHADERPERMUTATION_TRIPPY;
2043         if (depthrgb)
2044                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2045         if (skeletal)
2046                 permutation |= SHADERPERMUTATION_SKELETAL;
2047
2048         if (vid.allowalphatocoverage)
2049                 GL_AlphaToCoverage(false);
2050         switch (vid.renderpath)
2051         {
2052         case RENDERPATH_D3D9:
2053 #ifdef SUPPORTD3D
2054                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2055 #endif
2056                 break;
2057         case RENDERPATH_D3D10:
2058                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2059                 break;
2060         case RENDERPATH_D3D11:
2061                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2062                 break;
2063         case RENDERPATH_GL20:
2064         case RENDERPATH_GLES2:
2065                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2066                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2067                 break;
2068         case RENDERPATH_GL13:
2069         case RENDERPATH_GLES1:
2070                 R_Mesh_TexBind(0, 0);
2071                 R_Mesh_TexBind(1, 0);
2072                 break;
2073         case RENDERPATH_GL11:
2074                 R_Mesh_TexBind(0, 0);
2075                 break;
2076         case RENDERPATH_SOFT:
2077                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2078                 break;
2079         }
2080 }
2081
2082 extern qboolean r_shadow_usingdeferredprepass;
2083 extern rtexture_t *r_shadow_attenuationgradienttexture;
2084 extern rtexture_t *r_shadow_attenuation2dtexture;
2085 extern rtexture_t *r_shadow_attenuation3dtexture;
2086 extern qboolean r_shadow_usingshadowmap2d;
2087 extern qboolean r_shadow_usingshadowmaportho;
2088 extern float r_shadow_shadowmap_texturescale[2];
2089 extern float r_shadow_shadowmap_parameters[4];
2090 extern qboolean r_shadow_shadowmapvsdct;
2091 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2092 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2093 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2094 extern matrix4x4_t r_shadow_shadowmapmatrix;
2095 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2096 extern int r_shadow_prepass_width;
2097 extern int r_shadow_prepass_height;
2098 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2099 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2100 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2101 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2102
2103 #define BLENDFUNC_ALLOWS_COLORMOD      1
2104 #define BLENDFUNC_ALLOWS_FOG           2
2105 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2106 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2107 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2108 static int R_BlendFuncFlags(int src, int dst)
2109 {
2110         int r = 0;
2111
2112         // a blendfunc allows colormod if:
2113         // a) it can never keep the destination pixel invariant, or
2114         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2115         // this is to prevent unintended side effects from colormod
2116
2117         // a blendfunc allows fog if:
2118         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2119         // this is to prevent unintended side effects from fog
2120
2121         // these checks are the output of fogeval.pl
2122
2123         r |= BLENDFUNC_ALLOWS_COLORMOD;
2124         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2125         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2126         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2127         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2128         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2129         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2130         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2132         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2133         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2134         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2135         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2136         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2137         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2138         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2139         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2140         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2141         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2142         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2143         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2144         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2145
2146         return r;
2147 }
2148
2149 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)
2150 {
2151         // select a permutation of the lighting shader appropriate to this
2152         // combination of texture, entity, light source, and fogging, only use the
2153         // minimum features necessary to avoid wasting rendering time in the
2154         // fragment shader on features that are not being used
2155         unsigned int permutation = 0;
2156         unsigned int mode = 0;
2157         int blendfuncflags;
2158         static float dummy_colormod[3] = {1, 1, 1};
2159         float *colormod = rsurface.colormod;
2160         float m16f[16];
2161         matrix4x4_t tempmatrix;
2162         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2163         if (r_trippy.integer && !notrippy)
2164                 permutation |= SHADERPERMUTATION_TRIPPY;
2165         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2166                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2167         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2168                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2169         if (rsurfacepass == RSURFPASS_BACKGROUND)
2170         {
2171                 // distorted background
2172                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2173                 {
2174                         mode = SHADERMODE_WATER;
2175                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2176                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2177                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2178                         {
2179                                 // this is the right thing to do for wateralpha
2180                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2181                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2182                         }
2183                         else
2184                         {
2185                                 // this is the right thing to do for entity alpha
2186                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2187                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2188                         }
2189                 }
2190                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2191                 {
2192                         mode = SHADERMODE_REFRACTION;
2193                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2194                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2195                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2196                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2197                 }
2198                 else
2199                 {
2200                         mode = SHADERMODE_GENERIC;
2201                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2202                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2203                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2204                 }
2205                 if (vid.allowalphatocoverage)
2206                         GL_AlphaToCoverage(false);
2207         }
2208         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2209         {
2210                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2211                 {
2212                         switch(rsurface.texture->offsetmapping)
2213                         {
2214                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2215                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2216                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2217                         case OFFSETMAPPING_OFF: break;
2218                         }
2219                 }
2220                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2221                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2222                 // normalmap (deferred prepass), may use alpha test on diffuse
2223                 mode = SHADERMODE_DEFERREDGEOMETRY;
2224                 GL_BlendFunc(GL_ONE, GL_ZERO);
2225                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2226                 if (vid.allowalphatocoverage)
2227                         GL_AlphaToCoverage(false);
2228         }
2229         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2230         {
2231                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2232                 {
2233                         switch(rsurface.texture->offsetmapping)
2234                         {
2235                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2236                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2237                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2238                         case OFFSETMAPPING_OFF: break;
2239                         }
2240                 }
2241                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2242                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2243                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2244                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2245                 // light source
2246                 mode = SHADERMODE_LIGHTSOURCE;
2247                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2248                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2249                 if (diffusescale > 0)
2250                         permutation |= SHADERPERMUTATION_DIFFUSE;
2251                 if (specularscale > 0)
2252                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2253                 if (r_refdef.fogenabled)
2254                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2255                 if (rsurface.texture->colormapping)
2256                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2257                 if (r_shadow_usingshadowmap2d)
2258                 {
2259                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2260                         if(r_shadow_shadowmapvsdct)
2261                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2262
2263                         if (r_shadow_shadowmap2ddepthbuffer)
2264                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2265                 }
2266                 if (rsurface.texture->reflectmasktexture)
2267                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2268                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2269                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2270                 if (vid.allowalphatocoverage)
2271                         GL_AlphaToCoverage(false);
2272         }
2273         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2274         {
2275                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2276                 {
2277                         switch(rsurface.texture->offsetmapping)
2278                         {
2279                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2280                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2281                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2282                         case OFFSETMAPPING_OFF: break;
2283                         }
2284                 }
2285                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2286                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2287                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2288                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2289                 // unshaded geometry (fullbright or ambient model lighting)
2290                 mode = SHADERMODE_FLATCOLOR;
2291                 ambientscale = diffusescale = specularscale = 0;
2292                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2293                         permutation |= SHADERPERMUTATION_GLOW;
2294                 if (r_refdef.fogenabled)
2295                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2296                 if (rsurface.texture->colormapping)
2297                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2298                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2299                 {
2300                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2301                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2302
2303                         if (r_shadow_shadowmap2ddepthbuffer)
2304                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2305                 }
2306                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2307                         permutation |= SHADERPERMUTATION_REFLECTION;
2308                 if (rsurface.texture->reflectmasktexture)
2309                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2310                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2311                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2312                 // when using alphatocoverage, we don't need alphakill
2313                 if (vid.allowalphatocoverage)
2314                 {
2315                         if (r_transparent_alphatocoverage.integer)
2316                         {
2317                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2318                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2319                         }
2320                         else
2321                                 GL_AlphaToCoverage(false);
2322                 }
2323         }
2324         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2325         {
2326                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2327                 {
2328                         switch(rsurface.texture->offsetmapping)
2329                         {
2330                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2331                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2332                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2333                         case OFFSETMAPPING_OFF: break;
2334                         }
2335                 }
2336                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2337                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2338                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2339                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2340                 // directional model lighting
2341                 mode = SHADERMODE_LIGHTDIRECTION;
2342                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2343                         permutation |= SHADERPERMUTATION_GLOW;
2344                 permutation |= SHADERPERMUTATION_DIFFUSE;
2345                 if (specularscale > 0)
2346                         permutation |= SHADERPERMUTATION_SPECULAR;
2347                 if (r_refdef.fogenabled)
2348                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2349                 if (rsurface.texture->colormapping)
2350                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2351                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2352                 {
2353                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2354                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2355
2356                         if (r_shadow_shadowmap2ddepthbuffer)
2357                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2358                 }
2359                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2360                         permutation |= SHADERPERMUTATION_REFLECTION;
2361                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2362                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2363                 if (rsurface.texture->reflectmasktexture)
2364                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2365                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2366                 {
2367                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2368                         if (r_shadow_bouncegriddirectional)
2369                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2370                 }
2371                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2372                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2373                 // when using alphatocoverage, we don't need alphakill
2374                 if (vid.allowalphatocoverage)
2375                 {
2376                         if (r_transparent_alphatocoverage.integer)
2377                         {
2378                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2379                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2380                         }
2381                         else
2382                                 GL_AlphaToCoverage(false);
2383                 }
2384         }
2385         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2386         {
2387                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2388                 {
2389                         switch(rsurface.texture->offsetmapping)
2390                         {
2391                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2392                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2393                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2394                         case OFFSETMAPPING_OFF: break;
2395                         }
2396                 }
2397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2398                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2399                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2400                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2401                 // ambient model lighting
2402                 mode = SHADERMODE_LIGHTDIRECTION;
2403                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2404                         permutation |= SHADERPERMUTATION_GLOW;
2405                 if (r_refdef.fogenabled)
2406                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2407                 if (rsurface.texture->colormapping)
2408                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2409                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2410                 {
2411                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2412                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2413
2414                         if (r_shadow_shadowmap2ddepthbuffer)
2415                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2416                 }
2417                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2418                         permutation |= SHADERPERMUTATION_REFLECTION;
2419                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2420                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2421                 if (rsurface.texture->reflectmasktexture)
2422                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2423                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2424                 {
2425                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2426                         if (r_shadow_bouncegriddirectional)
2427                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2428                 }
2429                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2430                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2431                 // when using alphatocoverage, we don't need alphakill
2432                 if (vid.allowalphatocoverage)
2433                 {
2434                         if (r_transparent_alphatocoverage.integer)
2435                         {
2436                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2437                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2438                         }
2439                         else
2440                                 GL_AlphaToCoverage(false);
2441                 }
2442         }
2443         else
2444         {
2445                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2446                 {
2447                         switch(rsurface.texture->offsetmapping)
2448                         {
2449                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2450                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2451                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2452                         case OFFSETMAPPING_OFF: break;
2453                         }
2454                 }
2455                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2456                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2457                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2458                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2459                 // lightmapped wall
2460                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2461                         permutation |= SHADERPERMUTATION_GLOW;
2462                 if (r_refdef.fogenabled)
2463                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2464                 if (rsurface.texture->colormapping)
2465                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2466                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2467                 {
2468                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2469                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2470
2471                         if (r_shadow_shadowmap2ddepthbuffer)
2472                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2473                 }
2474                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2475                         permutation |= SHADERPERMUTATION_REFLECTION;
2476                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2477                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2478                 if (rsurface.texture->reflectmasktexture)
2479                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2480                 if (FAKELIGHT_ENABLED)
2481                 {
2482                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2483                         mode = SHADERMODE_FAKELIGHT;
2484                         permutation |= SHADERPERMUTATION_DIFFUSE;
2485                         if (specularscale > 0)
2486                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2487                 }
2488                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2489                 {
2490                         // deluxemapping (light direction texture)
2491                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2492                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2493                         else
2494                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2495                         permutation |= SHADERPERMUTATION_DIFFUSE;
2496                         if (specularscale > 0)
2497                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2498                 }
2499                 else if (r_glsl_deluxemapping.integer >= 2)
2500                 {
2501                         // fake deluxemapping (uniform light direction in tangentspace)
2502                         if (rsurface.uselightmaptexture)
2503                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2504                         else
2505                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2506                         permutation |= SHADERPERMUTATION_DIFFUSE;
2507                         if (specularscale > 0)
2508                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2509                 }
2510                 else if (rsurface.uselightmaptexture)
2511                 {
2512                         // ordinary lightmapping (q1bsp, q3bsp)
2513                         mode = SHADERMODE_LIGHTMAP;
2514                 }
2515                 else
2516                 {
2517                         // ordinary vertex coloring (q3bsp)
2518                         mode = SHADERMODE_VERTEXCOLOR;
2519                 }
2520                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2521                 {
2522                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2523                         if (r_shadow_bouncegriddirectional)
2524                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2525                 }
2526                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2527                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2528                 // when using alphatocoverage, we don't need alphakill
2529                 if (vid.allowalphatocoverage)
2530                 {
2531                         if (r_transparent_alphatocoverage.integer)
2532                         {
2533                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2534                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2535                         }
2536                         else
2537                                 GL_AlphaToCoverage(false);
2538                 }
2539         }
2540         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2541                 colormod = dummy_colormod;
2542         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2543                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2544         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2545                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2546         switch(vid.renderpath)
2547         {
2548         case RENDERPATH_D3D9:
2549 #ifdef SUPPORTD3D
2550                 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);
2551                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2552                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2553                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2554                 if (mode == SHADERMODE_LIGHTSOURCE)
2555                 {
2556                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2557                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2558                 }
2559                 else
2560                 {
2561                         if (mode == SHADERMODE_LIGHTDIRECTION)
2562                         {
2563                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2564                         }
2565                 }
2566                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2567                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2568                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2569                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2570                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2571
2572                 if (mode == SHADERMODE_LIGHTSOURCE)
2573                 {
2574                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2575                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2576                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2577                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2578                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2579
2580                         // additive passes are only darkened by fog, not tinted
2581                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2582                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2583                 }
2584                 else
2585                 {
2586                         if (mode == SHADERMODE_FLATCOLOR)
2587                         {
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2589                         }
2590                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2591                         {
2592                                 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]);
2593                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[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], colormod[1], colormod[2]);
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2599                         }
2600                         else
2601                         {
2602                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2603                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2604                                 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);
2605                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2606                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2607                         }
2608                         // additive passes are only darkened by fog, not tinted
2609                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2610                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2611                         else
2612                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2613                         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);
2614                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2615                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2616                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2617                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2618                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2619                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2620                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2621                         if (mode == SHADERMODE_WATER)
2622                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2623                 }
2624                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2625                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2626                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2627                 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));
2628                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2629                 if (rsurface.texture->pantstexture)
2630                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2631                 else
2632                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2633                 if (rsurface.texture->shirttexture)
2634                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2635                 else
2636                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2637                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2638                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2639                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2640                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2641                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2642                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2643                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2644                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2645                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2646                         );
2647                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2648                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2649                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2650                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2651
2652                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2653                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2654                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2655                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2656                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2657                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2658                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2659                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2660                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2661                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2662                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2663                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2664                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2665                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2666                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2667                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2668                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2669                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2670                 {
2671                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2672                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2673                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2674                 }
2675                 else
2676                 {
2677                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2678                 }
2679 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2680                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2681                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2682                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2683                 {
2684                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2685                         if (rsurface.rtlight)
2686                         {
2687                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2688                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2689                         }
2690                 }
2691 #endif
2692                 break;
2693         case RENDERPATH_D3D10:
2694                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2695                 break;
2696         case RENDERPATH_D3D11:
2697                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2698                 break;
2699         case RENDERPATH_GL20:
2700         case RENDERPATH_GLES2:
2701                 if (!vid.useinterleavedarrays)
2702                 {
2703                         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);
2704                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2705                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2706                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2707                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2708                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2709                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2710                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2711                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2712                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2713                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2714                 }
2715                 else
2716                 {
2717                         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);
2718                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2719                 }
2720                 // this has to be after RSurf_PrepareVerticesForBatch
2721                 if (rsurface.batchskeletaltransform3x4buffer)
2722                         permutation |= SHADERPERMUTATION_SKELETAL;
2723                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2724                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2725                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2726                 if (mode == SHADERMODE_LIGHTSOURCE)
2727                 {
2728                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2729                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2730                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2731                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2732                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2733                         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);
2734         
2735                         // additive passes are only darkened by fog, not tinted
2736                         if (r_glsl_permutation->loc_FogColor >= 0)
2737                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2738                         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);
2739                 }
2740                 else
2741                 {
2742                         if (mode == SHADERMODE_FLATCOLOR)
2743                         {
2744                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2745                         }
2746                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2747                         {
2748                                 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]);
2749                                 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]);
2750                                 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);
2751                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2752                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2753                                 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]);
2754                                 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]);
2755                         }
2756                         else
2757                         {
2758                                 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]);
2759                                 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]);
2760                                 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);
2761                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2762                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2763                         }
2764                         // additive passes are only darkened by fog, not tinted
2765                         if (r_glsl_permutation->loc_FogColor >= 0)
2766                         {
2767                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2768                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2769                                 else
2770                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2771                         }
2772                         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);
2773                         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]);
2774                         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]);
2775                         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]);
2776                         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]);
2777                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2778                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2779                         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);
2780                         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]);
2781                 }
2782                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2783                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2784                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2785                 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]);
2786                 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]);
2787
2788                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2789                 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));
2790                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2791                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2792                 {
2793                         if (rsurface.texture->pantstexture)
2794                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2795                         else
2796                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2797                 }
2798                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2799                 {
2800                         if (rsurface.texture->shirttexture)
2801                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2802                         else
2803                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2804                 }
2805                 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]);
2806                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2807                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2808                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2809                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2810                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2811                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2812                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2813                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2814                         );
2815                 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);
2816                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2817                 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]);
2818                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2819                 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);}
2820                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2821
2822                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2823                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2824                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2825                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2826                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2827                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2828                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2829                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2830                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2831                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2832                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2833                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2834                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2835                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2836                 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);
2837                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2838                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2839                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2840                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2841                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2842                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2843                 {
2844                         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);
2845                         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);
2846                         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);
2847                 }
2848                 else
2849                 {
2850                         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);
2851                 }
2852                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2853                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2854                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2855                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2856                 {
2857                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2858                         if (rsurface.rtlight)
2859                         {
2860                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2861                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2862                         }
2863                 }
2864                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2865                 CHECKGLERROR
2866                 break;
2867         case RENDERPATH_GL11:
2868         case RENDERPATH_GL13:
2869         case RENDERPATH_GLES1:
2870                 break;
2871         case RENDERPATH_SOFT:
2872                 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);
2873                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2874                 R_SetupShader_SetPermutationSoft(mode, permutation);
2875                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2876                 if (mode == SHADERMODE_LIGHTSOURCE)
2877                 {
2878                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2879                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2880                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2881                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2882                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2884         
2885                         // additive passes are only darkened by fog, not tinted
2886                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2887                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2888                 }
2889                 else
2890                 {
2891                         if (mode == SHADERMODE_FLATCOLOR)
2892                         {
2893                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2894                         }
2895                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2896                         {
2897                                 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]);
2898                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2899                                 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);
2900                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2902                                 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]);
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2904                         }
2905                         else
2906                         {
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2909                                 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);
2910                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2912                         }
2913                         // additive passes are only darkened by fog, not tinted
2914                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2916                         else
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2918                         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);
2919                         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]);
2920                         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]);
2921                         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]);
2922                         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]);
2923                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2924                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2925                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2926                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2927                 }
2928                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2929                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2930                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2931                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2932                 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]);
2933
2934                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2935                 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));
2936                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2937                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2938                 {
2939                         if (rsurface.texture->pantstexture)
2940                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2941                         else
2942                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2943                 }
2944                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2945                 {
2946                         if (rsurface.texture->shirttexture)
2947                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2948                         else
2949                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2950                 }
2951                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2952                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2953                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2954                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2955                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2956                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2957                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2958                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2959                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2960                         );
2961                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2962                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2963                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2964                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2965
2966                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2967                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2968                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2969                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2970                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2971                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2972                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2973                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2974                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2975                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2976                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2977                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2978                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2979                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2980                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2981                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2982                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2983                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2984                 {
2985                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2986                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2987                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2988                 }
2989                 else
2990                 {
2991                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2992                 }
2993 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2994                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2995                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2996                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2997                 {
2998                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2999                         if (rsurface.rtlight)
3000                         {
3001                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3002                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3003                         }
3004                 }
3005                 break;
3006         }
3007 }
3008
3009 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3010 {
3011         // select a permutation of the lighting shader appropriate to this
3012         // combination of texture, entity, light source, and fogging, only use the
3013         // minimum features necessary to avoid wasting rendering time in the
3014         // fragment shader on features that are not being used
3015         unsigned int permutation = 0;
3016         unsigned int mode = 0;
3017         const float *lightcolorbase = rtlight->currentcolor;
3018         float ambientscale = rtlight->ambientscale;
3019         float diffusescale = rtlight->diffusescale;
3020         float specularscale = rtlight->specularscale;
3021         // this is the location of the light in view space
3022         vec3_t viewlightorigin;
3023         // this transforms from view space (camera) to light space (cubemap)
3024         matrix4x4_t viewtolight;
3025         matrix4x4_t lighttoview;
3026         float viewtolight16f[16];
3027         // light source
3028         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3029         if (rtlight->currentcubemap != r_texture_whitecube)
3030                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3031         if (diffusescale > 0)
3032                 permutation |= SHADERPERMUTATION_DIFFUSE;
3033         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3034                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3035         if (r_shadow_usingshadowmap2d)
3036         {
3037                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3038                 if (r_shadow_shadowmapvsdct)
3039                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3040
3041                 if (r_shadow_shadowmap2ddepthbuffer)
3042                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3043         }
3044         if (vid.allowalphatocoverage)
3045                 GL_AlphaToCoverage(false);
3046         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3047         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3048         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3049         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3050         switch(vid.renderpath)
3051         {
3052         case RENDERPATH_D3D9:
3053 #ifdef SUPPORTD3D
3054                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3055                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3056                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3057                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3058                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3059                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3060                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3061                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3062                 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);
3063                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3064                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3065
3066                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3067                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3068                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3069                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3070                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3071 #endif
3072                 break;
3073         case RENDERPATH_D3D10:
3074                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3075                 break;
3076         case RENDERPATH_D3D11:
3077                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3078                 break;
3079         case RENDERPATH_GL20:
3080         case RENDERPATH_GLES2:
3081                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3082                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3083                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3084                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3085                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3086                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3087                 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]);
3088                 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]);
3089                 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);
3090                 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]);
3091                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3092
3093                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3094                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3095                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3096                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3097                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3098                 break;
3099         case RENDERPATH_GL11:
3100         case RENDERPATH_GL13:
3101         case RENDERPATH_GLES1:
3102                 break;
3103         case RENDERPATH_SOFT:
3104                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3105                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3106                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3107                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3108                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3109                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3110                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3111                 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]);
3112                 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);
3113                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3114                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3115
3116                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3117                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3118                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3119                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3120                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3121                 break;
3122         }
3123 }
3124
3125 #define SKINFRAME_HASH 1024
3126
3127 typedef struct
3128 {
3129         int loadsequence; // incremented each level change
3130         memexpandablearray_t array;
3131         skinframe_t *hash[SKINFRAME_HASH];
3132 }
3133 r_skinframe_t;
3134 r_skinframe_t r_skinframe;
3135
3136 void R_SkinFrame_PrepareForPurge(void)
3137 {
3138         r_skinframe.loadsequence++;
3139         // wrap it without hitting zero
3140         if (r_skinframe.loadsequence >= 200)
3141                 r_skinframe.loadsequence = 1;
3142 }
3143
3144 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3145 {
3146         if (!skinframe)
3147                 return;
3148         // mark the skinframe as used for the purging code
3149         skinframe->loadsequence = r_skinframe.loadsequence;
3150 }
3151
3152 void R_SkinFrame_Purge(void)
3153 {
3154         int i;
3155         skinframe_t *s;
3156         for (i = 0;i < SKINFRAME_HASH;i++)
3157         {
3158                 for (s = r_skinframe.hash[i];s;s = s->next)
3159                 {
3160                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3161                         {
3162                                 if (s->merged == s->base)
3163                                         s->merged = NULL;
3164                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3165                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3166                                 R_PurgeTexture(s->merged);s->merged = NULL;
3167                                 R_PurgeTexture(s->base  );s->base   = NULL;
3168                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3169                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3170                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3171                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3172                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3173                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3174                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3175                                 s->loadsequence = 0;
3176                         }
3177                 }
3178         }
3179 }
3180
3181 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3182         skinframe_t *item;
3183         char basename[MAX_QPATH];
3184
3185         Image_StripImageExtension(name, basename, sizeof(basename));
3186
3187         if( last == NULL ) {
3188                 int hashindex;
3189                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3190                 item = r_skinframe.hash[hashindex];
3191         } else {
3192                 item = last->next;
3193         }
3194
3195         // linearly search through the hash bucket
3196         for( ; item ; item = item->next ) {
3197                 if( !strcmp( item->basename, basename ) ) {
3198                         return item;
3199                 }
3200         }
3201         return NULL;
3202 }
3203
3204 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3205 {
3206         skinframe_t *item;
3207         int hashindex;
3208         char basename[MAX_QPATH];
3209
3210         Image_StripImageExtension(name, basename, sizeof(basename));
3211
3212         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3213         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3214                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3215                         break;
3216
3217         if (!item) {
3218                 rtexture_t *dyntexture;
3219                 // check whether its a dynamic texture
3220                 dyntexture = CL_GetDynTexture( basename );
3221                 if (!add && !dyntexture)
3222                         return NULL;
3223                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3224                 memset(item, 0, sizeof(*item));
3225                 strlcpy(item->basename, basename, sizeof(item->basename));
3226                 item->base = dyntexture; // either NULL or dyntexture handle
3227                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3228                 item->comparewidth = comparewidth;
3229                 item->compareheight = compareheight;
3230                 item->comparecrc = comparecrc;
3231                 item->next = r_skinframe.hash[hashindex];
3232                 r_skinframe.hash[hashindex] = item;
3233         }
3234         else if (textureflags & TEXF_FORCE_RELOAD)
3235         {
3236                 rtexture_t *dyntexture;
3237                 // check whether its a dynamic texture
3238                 dyntexture = CL_GetDynTexture( basename );
3239                 if (!add && !dyntexture)
3240                         return NULL;
3241                 if (item->merged == item->base)
3242                         item->merged = NULL;
3243                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3244                 R_PurgeTexture(item->stain );item->stain  = NULL;
3245                 R_PurgeTexture(item->merged);item->merged = NULL;
3246                 R_PurgeTexture(item->base  );item->base   = NULL;
3247                 R_PurgeTexture(item->pants );item->pants  = NULL;
3248                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3249                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3250                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3251                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3252                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3253         R_PurgeTexture(item->reflect);item->reflect = NULL;
3254                 item->loadsequence = 0;
3255         }
3256         else if( item->base == NULL )
3257         {
3258                 rtexture_t *dyntexture;
3259                 // check whether its a dynamic texture
3260                 // 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]
3261                 dyntexture = CL_GetDynTexture( basename );
3262                 item->base = dyntexture; // either NULL or dyntexture handle
3263         }
3264
3265         R_SkinFrame_MarkUsed(item);
3266         return item;
3267 }
3268
3269 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3270         { \
3271                 unsigned long long avgcolor[5], wsum; \
3272                 int pix, comp, w; \
3273                 avgcolor[0] = 0; \
3274                 avgcolor[1] = 0; \
3275                 avgcolor[2] = 0; \
3276                 avgcolor[3] = 0; \
3277                 avgcolor[4] = 0; \
3278                 wsum = 0; \
3279                 for(pix = 0; pix < cnt; ++pix) \
3280                 { \
3281                         w = 0; \
3282                         for(comp = 0; comp < 3; ++comp) \
3283                                 w += getpixel; \
3284                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3285                         { \
3286                                 ++wsum; \
3287                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3288                                 w = getpixel; \
3289                                 for(comp = 0; comp < 3; ++comp) \
3290                                         avgcolor[comp] += getpixel * w; \
3291                                 avgcolor[3] += w; \
3292                         } \
3293                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3294                         avgcolor[4] += getpixel; \
3295                 } \
3296                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3297                         avgcolor[3] = 1; \
3298                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3299                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3300                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3301                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3302         }
3303
3304 extern cvar_t gl_picmip;
3305 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3306 {
3307         int j;
3308         unsigned char *pixels;
3309         unsigned char *bumppixels;
3310         unsigned char *basepixels = NULL;
3311         int basepixels_width = 0;
3312         int basepixels_height = 0;
3313         skinframe_t *skinframe;
3314         rtexture_t *ddsbase = NULL;
3315         qboolean ddshasalpha = false;
3316         float ddsavgcolor[4];
3317         char basename[MAX_QPATH];
3318         int miplevel = R_PicmipForFlags(textureflags);
3319         int savemiplevel = miplevel;
3320         int mymiplevel;
3321         char vabuf[1024];
3322
3323         if (cls.state == ca_dedicated)
3324                 return NULL;
3325
3326         // return an existing skinframe if already loaded
3327         // if loading of the first image fails, don't make a new skinframe as it
3328         // would cause all future lookups of this to be missing
3329         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3330         if (skinframe && skinframe->base)
3331                 return skinframe;
3332
3333         Image_StripImageExtension(name, basename, sizeof(basename));
3334
3335         // check for DDS texture file first
3336         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3337         {
3338                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3339                 if (basepixels == NULL)
3340                         return NULL;
3341         }
3342
3343         // FIXME handle miplevel
3344
3345         if (developer_loading.integer)
3346                 Con_Printf("loading skin \"%s\"\n", name);
3347
3348         // we've got some pixels to store, so really allocate this new texture now
3349         if (!skinframe)
3350                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3351         textureflags &= ~TEXF_FORCE_RELOAD;
3352         skinframe->stain = NULL;
3353         skinframe->merged = NULL;
3354         skinframe->base = NULL;
3355         skinframe->pants = NULL;
3356         skinframe->shirt = NULL;
3357         skinframe->nmap = NULL;
3358         skinframe->gloss = NULL;
3359         skinframe->glow = NULL;
3360         skinframe->fog = NULL;
3361         skinframe->reflect = NULL;
3362         skinframe->hasalpha = false;
3363
3364         if (ddsbase)
3365         {
3366                 skinframe->base = ddsbase;
3367                 skinframe->hasalpha = ddshasalpha;
3368                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3369                 if (r_loadfog && skinframe->hasalpha)
3370                         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);
3371                 //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]);
3372         }
3373         else
3374         {
3375                 basepixels_width = image_width;
3376                 basepixels_height = image_height;
3377                 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);
3378                 if (textureflags & TEXF_ALPHA)
3379                 {
3380                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3381                         {
3382                                 if (basepixels[j] < 255)
3383                                 {
3384                                         skinframe->hasalpha = true;
3385                                         break;
3386                                 }
3387                         }
3388                         if (r_loadfog && skinframe->hasalpha)
3389                         {
3390                                 // has transparent pixels
3391                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3392                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3393                                 {
3394                                         pixels[j+0] = 255;
3395                                         pixels[j+1] = 255;
3396                                         pixels[j+2] = 255;
3397                                         pixels[j+3] = basepixels[j+3];
3398                                 }
3399                                 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);
3400                                 Mem_Free(pixels);
3401                         }
3402                 }
3403                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3404 #ifndef USE_GLES2
3405                 //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]);
3406                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3407                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3408                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3409                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3410 #endif
3411         }
3412
3413         if (r_loaddds)
3414         {
3415                 mymiplevel = savemiplevel;
3416                 if (r_loadnormalmap)
3417                         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);
3418                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3419                 if (r_loadgloss)
3420                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3421                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3422                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3423                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3424         }
3425
3426         // _norm is the name used by tenebrae and has been adopted as standard
3427         if (r_loadnormalmap && skinframe->nmap == NULL)
3428         {
3429                 mymiplevel = savemiplevel;
3430                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3431                 {
3432                         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);
3433                         Mem_Free(pixels);
3434                         pixels = NULL;
3435                 }
3436                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3437                 {
3438                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3439                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3440                         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);
3441                         Mem_Free(pixels);
3442                         Mem_Free(bumppixels);
3443                 }
3444                 else if (r_shadow_bumpscale_basetexture.value > 0)
3445                 {
3446                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3447                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3448                         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);
3449                         Mem_Free(pixels);
3450                 }
3451 #ifndef USE_GLES2
3452                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3453                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3454 #endif
3455         }
3456
3457         // _luma is supported only for tenebrae compatibility
3458         // _glow is the preferred name
3459         mymiplevel = savemiplevel;
3460         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))))
3461         {
3462                 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);
3463 #ifndef USE_GLES2
3464                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3465                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3466 #endif
3467                 Mem_Free(pixels);pixels = NULL;
3468         }
3469
3470         mymiplevel = savemiplevel;
3471         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3472         {
3473                 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);
3474 #ifndef USE_GLES2
3475                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3476                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3477 #endif
3478                 Mem_Free(pixels);
3479                 pixels = NULL;
3480         }
3481
3482         mymiplevel = savemiplevel;
3483         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3484         {
3485                 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);
3486 #ifndef USE_GLES2
3487                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3488                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3489 #endif
3490                 Mem_Free(pixels);
3491                 pixels = NULL;
3492         }
3493
3494         mymiplevel = savemiplevel;
3495         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3496         {
3497                 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);
3498 #ifndef USE_GLES2
3499                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3500                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3501 #endif
3502                 Mem_Free(pixels);
3503                 pixels = NULL;
3504         }
3505
3506         mymiplevel = savemiplevel;
3507         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3508         {
3509                 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);
3510 #ifndef USE_GLES2
3511                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3512                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3513 #endif
3514                 Mem_Free(pixels);
3515                 pixels = NULL;
3516         }
3517
3518         if (basepixels)
3519                 Mem_Free(basepixels);
3520
3521         return skinframe;
3522 }
3523
3524 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3525 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3526 {
3527         int i;
3528         unsigned char *temp1, *temp2;
3529         skinframe_t *skinframe;
3530         char vabuf[1024];
3531
3532         if (cls.state == ca_dedicated)
3533                 return NULL;
3534
3535         // if already loaded just return it, otherwise make a new skinframe
3536         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3537         if (skinframe->base)
3538                 return skinframe;
3539         textureflags &= ~TEXF_FORCE_RELOAD;
3540
3541         skinframe->stain = NULL;
3542         skinframe->merged = NULL;
3543         skinframe->base = NULL;
3544         skinframe->pants = NULL;
3545         skinframe->shirt = NULL;
3546         skinframe->nmap = NULL;
3547         skinframe->gloss = NULL;
3548         skinframe->glow = NULL;
3549         skinframe->fog = NULL;
3550         skinframe->reflect = NULL;
3551         skinframe->hasalpha = false;
3552
3553         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3554         if (!skindata)
3555                 return NULL;
3556
3557         if (developer_loading.integer)
3558                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3559
3560         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3561         {
3562                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3563                 temp2 = temp1 + width * height * 4;
3564                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3565                 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);
3566                 Mem_Free(temp1);
3567         }
3568         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3569         if (textureflags & TEXF_ALPHA)
3570         {
3571                 for (i = 3;i < width * height * 4;i += 4)
3572                 {
3573                         if (skindata[i] < 255)
3574                         {
3575                                 skinframe->hasalpha = true;
3576                                 break;
3577                         }
3578                 }
3579                 if (r_loadfog && skinframe->hasalpha)
3580                 {
3581                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3582                         memcpy(fogpixels, skindata, width * height * 4);
3583                         for (i = 0;i < width * height * 4;i += 4)
3584                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3585                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3586                         Mem_Free(fogpixels);
3587                 }
3588         }
3589
3590         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3591         //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]);
3592
3593         return skinframe;
3594 }
3595
3596 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3597 {
3598         int i;
3599         int featuresmask;
3600         skinframe_t *skinframe;
3601
3602         if (cls.state == ca_dedicated)
3603                 return NULL;
3604
3605         // if already loaded just return it, otherwise make a new skinframe
3606         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3607         if (skinframe->base)
3608                 return skinframe;
3609         //textureflags &= ~TEXF_FORCE_RELOAD;
3610
3611         skinframe->stain = NULL;
3612         skinframe->merged = NULL;
3613         skinframe->base = NULL;
3614         skinframe->pants = NULL;
3615         skinframe->shirt = NULL;
3616         skinframe->nmap = NULL;
3617         skinframe->gloss = NULL;
3618         skinframe->glow = NULL;
3619         skinframe->fog = NULL;
3620         skinframe->reflect = NULL;
3621         skinframe->hasalpha = false;
3622
3623         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3624         if (!skindata)
3625                 return NULL;
3626
3627         if (developer_loading.integer)
3628                 Con_Printf("loading quake skin \"%s\"\n", name);
3629
3630         // 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)
3631         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3632         memcpy(skinframe->qpixels, skindata, width*height);
3633         skinframe->qwidth = width;
3634         skinframe->qheight = height;
3635
3636         featuresmask = 0;
3637         for (i = 0;i < width * height;i++)
3638                 featuresmask |= palette_featureflags[skindata[i]];
3639
3640         skinframe->hasalpha = false;
3641         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3642         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3643         skinframe->qgeneratemerged = true;
3644         skinframe->qgeneratebase = skinframe->qhascolormapping;
3645         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3646
3647         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3648         //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]);
3649
3650         return skinframe;
3651 }
3652
3653 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3654 {
3655         int width;
3656         int height;
3657         unsigned char *skindata;
3658         char vabuf[1024];
3659
3660         if (!skinframe->qpixels)
3661                 return;
3662
3663         if (!skinframe->qhascolormapping)
3664                 colormapped = false;
3665
3666         if (colormapped)
3667         {
3668                 if (!skinframe->qgeneratebase)
3669                         return;
3670         }
3671         else
3672         {
3673                 if (!skinframe->qgeneratemerged)
3674                         return;
3675         }
3676
3677         width = skinframe->qwidth;
3678         height = skinframe->qheight;
3679         skindata = skinframe->qpixels;
3680
3681         if (skinframe->qgeneratenmap)
3682         {
3683                 unsigned char *temp1, *temp2;
3684                 skinframe->qgeneratenmap = false;
3685                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3686                 temp2 = temp1 + width * height * 4;
3687                 // use either a custom palette or the quake palette
3688                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3689                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3690                 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);
3691                 Mem_Free(temp1);
3692         }
3693
3694         if (skinframe->qgenerateglow)
3695         {
3696                 skinframe->qgenerateglow = false;
3697                 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
3698         }
3699
3700         if (colormapped)
3701         {
3702                 skinframe->qgeneratebase = false;
3703                 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);
3704                 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);
3705                 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);
3706         }
3707         else
3708         {
3709                 skinframe->qgeneratemerged = false;
3710                 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);
3711         }
3712
3713         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3714         {
3715                 Mem_Free(skinframe->qpixels);
3716                 skinframe->qpixels = NULL;
3717         }
3718 }
3719
3720 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)
3721 {
3722         int i;
3723         skinframe_t *skinframe;
3724         char vabuf[1024];
3725
3726         if (cls.state == ca_dedicated)
3727                 return NULL;
3728
3729         // if already loaded just return it, otherwise make a new skinframe
3730         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3731         if (skinframe->base)
3732                 return skinframe;
3733         textureflags &= ~TEXF_FORCE_RELOAD;
3734
3735         skinframe->stain = NULL;
3736         skinframe->merged = NULL;
3737         skinframe->base = NULL;
3738         skinframe->pants = NULL;
3739         skinframe->shirt = NULL;
3740         skinframe->nmap = NULL;
3741         skinframe->gloss = NULL;
3742         skinframe->glow = NULL;
3743         skinframe->fog = NULL;
3744         skinframe->reflect = NULL;
3745         skinframe->hasalpha = false;
3746
3747         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3748         if (!skindata)
3749                 return NULL;
3750
3751         if (developer_loading.integer)
3752                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3753
3754         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3755         if (textureflags & TEXF_ALPHA)
3756         {
3757                 for (i = 0;i < width * height;i++)
3758                 {
3759                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3760                         {
3761                                 skinframe->hasalpha = true;
3762                                 break;
3763                         }
3764                 }
3765                 if (r_loadfog && skinframe->hasalpha)
3766                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3767         }
3768
3769         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3770         //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]);
3771
3772         return skinframe;
3773 }
3774
3775 skinframe_t *R_SkinFrame_LoadMissing(void)
3776 {
3777         skinframe_t *skinframe;
3778
3779         if (cls.state == ca_dedicated)
3780                 return NULL;
3781
3782         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3783         skinframe->stain = NULL;
3784         skinframe->merged = NULL;
3785         skinframe->base = NULL;
3786         skinframe->pants = NULL;
3787         skinframe->shirt = NULL;
3788         skinframe->nmap = NULL;
3789         skinframe->gloss = NULL;
3790         skinframe->glow = NULL;
3791         skinframe->fog = NULL;
3792         skinframe->reflect = NULL;
3793         skinframe->hasalpha = false;
3794
3795         skinframe->avgcolor[0] = rand() / RAND_MAX;
3796         skinframe->avgcolor[1] = rand() / RAND_MAX;
3797         skinframe->avgcolor[2] = rand() / RAND_MAX;
3798         skinframe->avgcolor[3] = 1;
3799
3800         return skinframe;
3801 }
3802
3803 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3804 typedef struct suffixinfo_s
3805 {
3806         const char *suffix;
3807         qboolean flipx, flipy, flipdiagonal;
3808 }
3809 suffixinfo_t;
3810 static suffixinfo_t suffix[3][6] =
3811 {
3812         {
3813                 {"px",   false, false, false},
3814                 {"nx",   false, false, false},
3815                 {"py",   false, false, false},
3816                 {"ny",   false, false, false},
3817                 {"pz",   false, false, false},
3818                 {"nz",   false, false, false}
3819         },
3820         {
3821                 {"posx", false, false, false},
3822                 {"negx", false, false, false},
3823                 {"posy", false, false, false},
3824                 {"negy", false, false, false},
3825                 {"posz", false, false, false},
3826                 {"negz", false, false, false}
3827         },
3828         {
3829                 {"rt",    true, false,  true},
3830                 {"lf",   false,  true,  true},
3831                 {"ft",    true,  true, false},
3832                 {"bk",   false, false, false},
3833                 {"up",    true, false,  true},
3834                 {"dn",    true, false,  true}
3835         }
3836 };
3837
3838 static int componentorder[4] = {0, 1, 2, 3};
3839
3840 static rtexture_t *R_LoadCubemap(const char *basename)
3841 {
3842         int i, j, cubemapsize;
3843         unsigned char *cubemappixels, *image_buffer;
3844         rtexture_t *cubemaptexture;
3845         char name[256];
3846         // must start 0 so the first loadimagepixels has no requested width/height
3847         cubemapsize = 0;
3848         cubemappixels = NULL;
3849         cubemaptexture = NULL;
3850         // keep trying different suffix groups (posx, px, rt) until one loads
3851         for (j = 0;j < 3 && !cubemappixels;j++)
3852         {
3853                 // load the 6 images in the suffix group
3854                 for (i = 0;i < 6;i++)
3855                 {
3856                         // generate an image name based on the base and and suffix
3857                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3858                         // load it
3859                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3860                         {
3861                                 // an image loaded, make sure width and height are equal
3862                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3863                                 {
3864                                         // if this is the first image to load successfully, allocate the cubemap memory
3865                                         if (!cubemappixels && image_width >= 1)
3866                                         {
3867                                                 cubemapsize = image_width;
3868                                                 // note this clears to black, so unavailable sides are black
3869                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3870                                         }
3871                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3872                                         if (cubemappixels)
3873                                                 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);
3874                                 }
3875                                 else
3876                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3877                                 // free the image
3878                                 Mem_Free(image_buffer);
3879                         }
3880                 }
3881         }
3882         // if a cubemap loaded, upload it
3883         if (cubemappixels)
3884         {
3885                 if (developer_loading.integer)
3886                         Con_Printf("loading cubemap \"%s\"\n", basename);
3887
3888                 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);
3889                 Mem_Free(cubemappixels);
3890         }
3891         else
3892         {
3893                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3894                 if (developer_loading.integer)
3895                 {
3896                         Con_Printf("(tried tried images ");
3897                         for (j = 0;j < 3;j++)
3898                                 for (i = 0;i < 6;i++)
3899                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3900                         Con_Print(" and was unable to find any of them).\n");
3901                 }
3902         }
3903         return cubemaptexture;
3904 }
3905
3906 rtexture_t *R_GetCubemap(const char *basename)
3907 {
3908         int i;
3909         for (i = 0;i < r_texture_numcubemaps;i++)
3910                 if (r_texture_cubemaps[i] != NULL)
3911                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3912                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3913         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3914                 return r_texture_whitecube;
3915         r_texture_numcubemaps++;
3916         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3917         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3918         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3919         return r_texture_cubemaps[i]->texture;
3920 }
3921
3922 static void R_Main_FreeViewCache(void)
3923 {
3924         if (r_refdef.viewcache.entityvisible)
3925                 Mem_Free(r_refdef.viewcache.entityvisible);
3926         if (r_refdef.viewcache.world_pvsbits)
3927                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3928         if (r_refdef.viewcache.world_leafvisible)
3929                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3930         if (r_refdef.viewcache.world_surfacevisible)
3931                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3932         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3933 }
3934
3935 static void R_Main_ResizeViewCache(void)
3936 {
3937         int numentities = r_refdef.scene.numentities;
3938         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3939         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3940         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3941         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3942         if (r_refdef.viewcache.maxentities < numentities)
3943         {
3944                 r_refdef.viewcache.maxentities = numentities;
3945                 if (r_refdef.viewcache.entityvisible)
3946                         Mem_Free(r_refdef.viewcache.entityvisible);
3947                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3948         }
3949         if (r_refdef.viewcache.world_numclusters != numclusters)
3950         {
3951                 r_refdef.viewcache.world_numclusters = numclusters;
3952                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3953                 if (r_refdef.viewcache.world_pvsbits)
3954                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3955                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3956         }
3957         if (r_refdef.viewcache.world_numleafs != numleafs)
3958         {
3959                 r_refdef.viewcache.world_numleafs = numleafs;
3960                 if (r_refdef.viewcache.world_leafvisible)
3961                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3962                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3963         }
3964         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3965         {
3966                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3967                 if (r_refdef.viewcache.world_surfacevisible)
3968                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3969                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3970         }
3971 }
3972
3973 extern rtexture_t *loadingscreentexture;
3974 static void gl_main_start(void)
3975 {
3976         loadingscreentexture = NULL;
3977         r_texture_blanknormalmap = NULL;
3978         r_texture_white = NULL;
3979         r_texture_grey128 = NULL;
3980         r_texture_black = NULL;
3981         r_texture_whitecube = NULL;
3982         r_texture_normalizationcube = NULL;
3983         r_texture_fogattenuation = NULL;
3984         r_texture_fogheighttexture = NULL;
3985         r_texture_gammaramps = NULL;
3986         r_texture_numcubemaps = 0;
3987         r_uniformbufferalignment = 32;
3988
3989         r_loaddds = r_texture_dds_load.integer != 0;
3990         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3991
3992         switch(vid.renderpath)
3993         {
3994         case RENDERPATH_GL20:
3995         case RENDERPATH_D3D9:
3996         case RENDERPATH_D3D10:
3997         case RENDERPATH_D3D11:
3998         case RENDERPATH_SOFT:
3999         case RENDERPATH_GLES2:
4000                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4001                 Cvar_SetValueQuick(&gl_combine, 1);
4002                 Cvar_SetValueQuick(&r_glsl, 1);
4003                 r_loadnormalmap = true;
4004                 r_loadgloss = true;
4005                 r_loadfog = false;
4006                 if (vid.support.arb_uniform_buffer_object)
4007                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4008                 break;
4009         case RENDERPATH_GL13:
4010         case RENDERPATH_GLES1:
4011                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4012                 Cvar_SetValueQuick(&gl_combine, 1);
4013                 Cvar_SetValueQuick(&r_glsl, 0);
4014                 r_loadnormalmap = false;
4015                 r_loadgloss = false;
4016                 r_loadfog = true;
4017                 break;
4018         case RENDERPATH_GL11:
4019                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4020                 Cvar_SetValueQuick(&gl_combine, 0);
4021                 Cvar_SetValueQuick(&r_glsl, 0);
4022                 r_loadnormalmap = false;
4023                 r_loadgloss = false;
4024                 r_loadfog = true;
4025                 break;
4026         }
4027
4028         R_AnimCache_Free();
4029         R_FrameData_Reset();
4030         R_BufferData_Reset();
4031
4032         r_numqueries = 0;
4033         r_maxqueries = 0;
4034         memset(r_queries, 0, sizeof(r_queries));
4035
4036         r_qwskincache = NULL;
4037         r_qwskincache_size = 0;
4038
4039         // due to caching of texture_t references, the collision cache must be reset
4040         Collision_Cache_Reset(true);
4041
4042         // set up r_skinframe loading system for textures
4043         memset(&r_skinframe, 0, sizeof(r_skinframe));
4044         r_skinframe.loadsequence = 1;
4045         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4046
4047         r_main_texturepool = R_AllocTexturePool();
4048         R_BuildBlankTextures();
4049         R_BuildNoTexture();
4050         if (vid.support.arb_texture_cube_map)
4051         {
4052                 R_BuildWhiteCube();
4053                 R_BuildNormalizationCube();
4054         }
4055         r_texture_fogattenuation = NULL;
4056         r_texture_fogheighttexture = NULL;
4057         r_texture_gammaramps = NULL;
4058         //r_texture_fogintensity = NULL;
4059         memset(&r_fb, 0, sizeof(r_fb));
4060         r_glsl_permutation = NULL;
4061         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4062         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4063         glslshaderstring = NULL;
4064 #ifdef SUPPORTD3D
4065         r_hlsl_permutation = NULL;
4066         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4067         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4068 #endif
4069         hlslshaderstring = NULL;
4070         memset(&r_svbsp, 0, sizeof (r_svbsp));
4071
4072         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4073         r_texture_numcubemaps = 0;
4074
4075         r_refdef.fogmasktable_density = 0;
4076 }
4077
4078 static void gl_main_shutdown(void)
4079 {
4080         R_AnimCache_Free();
4081         R_FrameData_Reset();
4082         R_BufferData_Reset();
4083
4084         R_Main_FreeViewCache();
4085
4086         switch(vid.renderpath)
4087         {
4088         case RENDERPATH_GL11:
4089         case RENDERPATH_GL13:
4090         case RENDERPATH_GL20:
4091         case RENDERPATH_GLES1:
4092         case RENDERPATH_GLES2:
4093 #ifdef GL_SAMPLES_PASSED_ARB
4094                 if (r_maxqueries)
4095                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4096 #endif
4097                 break;
4098         case RENDERPATH_D3D9:
4099                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4100                 break;
4101         case RENDERPATH_D3D10:
4102                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4103                 break;
4104         case RENDERPATH_D3D11:
4105                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4106                 break;
4107         case RENDERPATH_SOFT:
4108                 break;
4109         }
4110
4111         r_numqueries = 0;
4112         r_maxqueries = 0;
4113         memset(r_queries, 0, sizeof(r_queries));
4114
4115         r_qwskincache = NULL;
4116         r_qwskincache_size = 0;
4117
4118         // clear out the r_skinframe state
4119         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4120         memset(&r_skinframe, 0, sizeof(r_skinframe));
4121
4122         if (r_svbsp.nodes)
4123                 Mem_Free(r_svbsp.nodes);
4124         memset(&r_svbsp, 0, sizeof (r_svbsp));
4125         R_FreeTexturePool(&r_main_texturepool);
4126         loadingscreentexture = NULL;
4127         r_texture_blanknormalmap = NULL;
4128         r_texture_white = NULL;
4129         r_texture_grey128 = NULL;
4130         r_texture_black = NULL;
4131         r_texture_whitecube = NULL;
4132         r_texture_normalizationcube = NULL;
4133         r_texture_fogattenuation = NULL;
4134         r_texture_fogheighttexture = NULL;
4135         r_texture_gammaramps = NULL;
4136         r_texture_numcubemaps = 0;
4137         //r_texture_fogintensity = NULL;
4138         memset(&r_fb, 0, sizeof(r_fb));
4139         R_GLSL_Restart_f();
4140
4141         r_glsl_permutation = NULL;
4142         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4143         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4144         glslshaderstring = NULL;
4145 #ifdef SUPPORTD3D
4146         r_hlsl_permutation = NULL;
4147         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4148         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4149 #endif
4150         hlslshaderstring = NULL;
4151 }
4152
4153 static void gl_main_newmap(void)
4154 {
4155         // FIXME: move this code to client
4156         char *entities, entname[MAX_QPATH];
4157         if (r_qwskincache)
4158                 Mem_Free(r_qwskincache);
4159         r_qwskincache = NULL;
4160         r_qwskincache_size = 0;
4161         if (cl.worldmodel)
4162         {
4163                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4164                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4165                 {
4166                         CL_ParseEntityLump(entities);
4167                         Mem_Free(entities);
4168                         return;
4169                 }
4170                 if (cl.worldmodel->brush.entities)
4171                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4172         }
4173         R_Main_FreeViewCache();
4174
4175         R_FrameData_Reset();
4176         R_BufferData_Reset();
4177 }
4178
4179 void GL_Main_Init(void)
4180 {
4181         int i;
4182         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4183
4184         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4185         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4186         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4187         if (gamemode == GAME_NEHAHRA)
4188         {
4189                 Cvar_RegisterVariable (&gl_fogenable);
4190                 Cvar_RegisterVariable (&gl_fogdensity);
4191                 Cvar_RegisterVariable (&gl_fogred);
4192                 Cvar_RegisterVariable (&gl_foggreen);
4193                 Cvar_RegisterVariable (&gl_fogblue);
4194                 Cvar_RegisterVariable (&gl_fogstart);
4195                 Cvar_RegisterVariable (&gl_fogend);
4196                 Cvar_RegisterVariable (&gl_skyclip);
4197         }
4198         Cvar_RegisterVariable(&r_motionblur);
4199         Cvar_RegisterVariable(&r_damageblur);
4200         Cvar_RegisterVariable(&r_motionblur_averaging);
4201         Cvar_RegisterVariable(&r_motionblur_randomize);
4202         Cvar_RegisterVariable(&r_motionblur_minblur);
4203         Cvar_RegisterVariable(&r_motionblur_maxblur);
4204         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4205         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4206         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4207         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4208         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4209         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4210         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4211         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4212         Cvar_RegisterVariable(&r_equalize_entities_by);
4213         Cvar_RegisterVariable(&r_equalize_entities_to);
4214         Cvar_RegisterVariable(&r_depthfirst);
4215         Cvar_RegisterVariable(&r_useinfinitefarclip);
4216         Cvar_RegisterVariable(&r_farclip_base);
4217         Cvar_RegisterVariable(&r_farclip_world);
4218         Cvar_RegisterVariable(&r_nearclip);
4219         Cvar_RegisterVariable(&r_deformvertexes);
4220         Cvar_RegisterVariable(&r_transparent);
4221         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4222         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4223         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4224         Cvar_RegisterVariable(&r_showoverdraw);
4225         Cvar_RegisterVariable(&r_showbboxes);
4226         Cvar_RegisterVariable(&r_showsurfaces);
4227         Cvar_RegisterVariable(&r_showtris);
4228         Cvar_RegisterVariable(&r_shownormals);
4229         Cvar_RegisterVariable(&r_showlighting);
4230         Cvar_RegisterVariable(&r_showshadowvolumes);
4231         Cvar_RegisterVariable(&r_showcollisionbrushes);
4232         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4233         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4234         Cvar_RegisterVariable(&r_showdisabledepthtest);
4235         Cvar_RegisterVariable(&r_drawportals);
4236         Cvar_RegisterVariable(&r_drawentities);
4237         Cvar_RegisterVariable(&r_draw2d);
4238         Cvar_RegisterVariable(&r_drawworld);
4239         Cvar_RegisterVariable(&r_cullentities_trace);
4240         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4241         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4242         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4243         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4244         Cvar_RegisterVariable(&r_sortentities);
4245         Cvar_RegisterVariable(&r_drawviewmodel);
4246         Cvar_RegisterVariable(&r_drawexteriormodel);
4247         Cvar_RegisterVariable(&r_speeds);
4248         Cvar_RegisterVariable(&r_fullbrights);
4249         Cvar_RegisterVariable(&r_wateralpha);
4250         Cvar_RegisterVariable(&r_dynamic);
4251         Cvar_RegisterVariable(&r_fakelight);
4252         Cvar_RegisterVariable(&r_fakelight_intensity);
4253         Cvar_RegisterVariable(&r_fullbright);
4254         Cvar_RegisterVariable(&r_shadows);
4255         Cvar_RegisterVariable(&r_shadows_darken);
4256         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4257         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4258         Cvar_RegisterVariable(&r_shadows_throwdistance);
4259         Cvar_RegisterVariable(&r_shadows_throwdirection);
4260         Cvar_RegisterVariable(&r_shadows_focus);
4261         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4262         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4263         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4264         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4265         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4266         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4267         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4268         Cvar_RegisterVariable(&r_fog_exp2);
4269         Cvar_RegisterVariable(&r_fog_clear);
4270         Cvar_RegisterVariable(&r_drawfog);
4271         Cvar_RegisterVariable(&r_transparentdepthmasking);
4272         Cvar_RegisterVariable(&r_transparent_sortmindist);
4273         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4274         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4275         Cvar_RegisterVariable(&r_texture_dds_load);
4276         Cvar_RegisterVariable(&r_texture_dds_save);
4277         Cvar_RegisterVariable(&r_textureunits);
4278         Cvar_RegisterVariable(&gl_combine);
4279         Cvar_RegisterVariable(&r_usedepthtextures);
4280         Cvar_RegisterVariable(&r_viewfbo);
4281         Cvar_RegisterVariable(&r_viewscale);
4282         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4283         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4284         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4285         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4286         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4287         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4288         Cvar_RegisterVariable(&r_glsl);
4289         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4290         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4291         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4292         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4293         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4294         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4295         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4296         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4298         Cvar_RegisterVariable(&r_glsl_postprocess);
4299         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4300         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4301         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4302         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4303         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4304         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4307         Cvar_RegisterVariable(&r_celshading);
4308         Cvar_RegisterVariable(&r_celoutlines);
4309
4310         Cvar_RegisterVariable(&r_water);
4311         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4312         Cvar_RegisterVariable(&r_water_clippingplanebias);
4313         Cvar_RegisterVariable(&r_water_refractdistort);
4314         Cvar_RegisterVariable(&r_water_reflectdistort);
4315         Cvar_RegisterVariable(&r_water_scissormode);
4316         Cvar_RegisterVariable(&r_water_lowquality);
4317         Cvar_RegisterVariable(&r_water_hideplayer);
4318         Cvar_RegisterVariable(&r_water_fbo);
4319
4320         Cvar_RegisterVariable(&r_lerpsprites);
4321         Cvar_RegisterVariable(&r_lerpmodels);
4322         Cvar_RegisterVariable(&r_lerplightstyles);
4323         Cvar_RegisterVariable(&r_waterscroll);
4324         Cvar_RegisterVariable(&r_bloom);
4325         Cvar_RegisterVariable(&r_bloom_colorscale);
4326         Cvar_RegisterVariable(&r_bloom_brighten);
4327         Cvar_RegisterVariable(&r_bloom_blur);
4328         Cvar_RegisterVariable(&r_bloom_resolution);
4329         Cvar_RegisterVariable(&r_bloom_colorexponent);
4330         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4331         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4332         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4333         Cvar_RegisterVariable(&r_hdr_glowintensity);
4334         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4335         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4336         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4337         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4338         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4339         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4342         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4343         Cvar_RegisterVariable(&developer_texturelogging);
4344         Cvar_RegisterVariable(&gl_lightmaps);
4345         Cvar_RegisterVariable(&r_test);
4346         Cvar_RegisterVariable(&r_batch_multidraw);
4347         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4348         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4349         Cvar_RegisterVariable(&r_glsl_skeletal);
4350         Cvar_RegisterVariable(&r_glsl_saturation);
4351         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4352         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4353         Cvar_RegisterVariable(&r_framedatasize);
4354         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4355                 Cvar_RegisterVariable(&r_bufferdatasize[i]);
4356         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4357                 Cvar_SetValue("r_fullbrights", 0);
4358         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4359 }
4360
4361 void Render_Init(void)
4362 {
4363         gl_backend_init();
4364         R_Textures_Init();
4365         GL_Main_Init();
4366         Font_Init();
4367         GL_Draw_Init();
4368         R_Shadow_Init();
4369         R_Sky_Init();
4370         GL_Surf_Init();
4371         Sbar_Init();
4372         R_Particles_Init();
4373         R_Explosion_Init();
4374         R_LightningBeams_Init();
4375         Mod_RenderInit();
4376 }
4377
4378 /*
4379 ===============
4380 GL_Init
4381 ===============
4382 */
4383 #ifndef USE_GLES2
4384 extern char *ENGINE_EXTENSIONS;
4385 void GL_Init (void)
4386 {
4387         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4388         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4389         gl_version = (const char *)qglGetString(GL_VERSION);
4390         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4391
4392         if (!gl_extensions)
4393                 gl_extensions = "";
4394         if (!gl_platformextensions)
4395                 gl_platformextensions = "";
4396
4397         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4398         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4399         Con_Printf("GL_VERSION: %s\n", gl_version);
4400         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4401         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4402
4403         VID_CheckExtensions();
4404
4405         // LordHavoc: report supported extensions
4406         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4407
4408         // clear to black (loading plaque will be seen over this)
4409         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4410 }
4411 #endif
4412
4413 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4414 {
4415         int i;
4416         mplane_t *p;
4417         if (r_trippy.integer)
4418                 return false;
4419         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4420         {
4421                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4422                 if (i == 4)
4423                         continue;
4424                 p = r_refdef.view.frustum + i;
4425                 switch(p->signbits)
4426                 {
4427                 default:
4428                 case 0:
4429                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4430                                 return true;
4431                         break;
4432                 case 1:
4433                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4434                                 return true;
4435                         break;
4436                 case 2:
4437                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4438                                 return true;
4439                         break;
4440                 case 3:
4441                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4442                                 return true;
4443                         break;
4444                 case 4:
4445                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4446                                 return true;
4447                         break;
4448                 case 5:
4449                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4450                                 return true;
4451                         break;
4452                 case 6:
4453                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 7:
4457                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 }
4461         }
4462         return false;
4463 }
4464
4465 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4466 {
4467         int i;
4468         const mplane_t *p;
4469         if (r_trippy.integer)
4470                 return false;
4471         for (i = 0;i < numplanes;i++)
4472         {
4473                 p = planes + i;
4474                 switch(p->signbits)
4475                 {
4476                 default:
4477                 case 0:
4478                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4479                                 return true;
4480                         break;
4481                 case 1:
4482                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4483                                 return true;
4484                         break;
4485                 case 2:
4486                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4487                                 return true;
4488                         break;
4489                 case 3:
4490                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4491                                 return true;
4492                         break;
4493                 case 4:
4494                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4495                                 return true;
4496                         break;
4497                 case 5:
4498                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4499                                 return true;
4500                         break;
4501                 case 6:
4502                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4503                                 return true;
4504                         break;
4505                 case 7:
4506                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4507                                 return true;
4508                         break;
4509                 }
4510         }
4511         return false;
4512 }
4513
4514 //==================================================================================
4515
4516 // LordHavoc: this stores temporary data used within the same frame
4517
4518 typedef struct r_framedata_mem_s
4519 {
4520         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4521         size_t size; // how much usable space
4522         size_t current; // how much space in use
4523         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4524         size_t wantedsize; // how much space was allocated
4525         unsigned char *data; // start of real data (16byte aligned)
4526 }
4527 r_framedata_mem_t;
4528
4529 static r_framedata_mem_t *r_framedata_mem;
4530
4531 void R_FrameData_Reset(void)
4532 {
4533         while (r_framedata_mem)
4534         {
4535                 r_framedata_mem_t *next = r_framedata_mem->purge;
4536                 Mem_Free(r_framedata_mem);
4537                 r_framedata_mem = next;
4538         }
4539 }
4540
4541 static void R_FrameData_Resize(qboolean mustgrow)
4542 {
4543         size_t wantedsize;
4544         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4545         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4546         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4547         {
4548                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4549                 newmem->wantedsize = wantedsize;
4550                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4551                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4552                 newmem->current = 0;
4553                 newmem->mark = 0;
4554                 newmem->purge = r_framedata_mem;
4555                 r_framedata_mem = newmem;
4556         }
4557 }
4558
4559 void R_FrameData_NewFrame(void)
4560 {
4561         R_FrameData_Resize(false);
4562         if (!r_framedata_mem)
4563                 return;
4564         // if we ran out of space on the last frame, free the old memory now
4565         while (r_framedata_mem->purge)
4566         {
4567                 // repeatedly remove the second item in the list, leaving only head
4568                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4569                 Mem_Free(r_framedata_mem->purge);
4570                 r_framedata_mem->purge = next;
4571         }
4572         // reset the current mem pointer
4573         r_framedata_mem->current = 0;
4574         r_framedata_mem->mark = 0;
4575 }
4576
4577 void *R_FrameData_Alloc(size_t size)
4578 {
4579         void *data;
4580         float newvalue;
4581
4582         // align to 16 byte boundary - the data pointer is already aligned, so we
4583         // only need to ensure the size of every allocation is also aligned
4584         size = (size + 15) & ~15;
4585
4586         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4587         {
4588                 // emergency - we ran out of space, allocate more memory
4589                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4590                 // this might not be a growing it, but we'll allocate another buffer every time
4591                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4592                 R_FrameData_Resize(true);
4593         }
4594
4595         data = r_framedata_mem->data + r_framedata_mem->current;
4596         r_framedata_mem->current += size;
4597
4598         // count the usage for stats
4599         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4600         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4601
4602         return (void *)data;
4603 }
4604
4605 void *R_FrameData_Store(size_t size, void *data)
4606 {
4607         void *d = R_FrameData_Alloc(size);
4608         if (d && data)
4609                 memcpy(d, data, size);
4610         return d;
4611 }
4612
4613 void R_FrameData_SetMark(void)
4614 {
4615         if (!r_framedata_mem)
4616                 return;
4617         r_framedata_mem->mark = r_framedata_mem->current;
4618 }
4619
4620 void R_FrameData_ReturnToMark(void)
4621 {
4622         if (!r_framedata_mem)
4623                 return;
4624         r_framedata_mem->current = r_framedata_mem->mark;
4625 }
4626
4627 //==================================================================================
4628
4629 // avoid reusing the same buffer objects on consecutive buffers
4630 #define R_BUFFERDATA_CYCLE 2
4631
4632 typedef struct r_bufferdata_buffer_s
4633 {
4634         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4635         size_t size; // how much usable space
4636         size_t current; // how much space in use
4637         r_meshbuffer_t *buffer; // the buffer itself
4638 }
4639 r_bufferdata_buffer_t;
4640
4641 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4642 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4643
4644 /// frees all dynamic buffers
4645 void R_BufferData_Reset(void)
4646 {
4647         int cycle, type;
4648         r_bufferdata_buffer_t **p, *mem;
4649         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4650         {
4651                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4652                 {
4653                         // free all buffers
4654                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type];
4655                         while (*p)
4656                         {
4657                                 mem = *p;
4658                                 *p = (*p)->purge;
4659                                 if (mem->buffer)
4660                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4661                                 Mem_Free(mem);
4662                         }
4663                 }
4664         }
4665 }
4666
4667 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4668 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow)
4669 {
4670         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4671         size_t size;
4672         size = (size_t)(r_bufferdatasize[type].value * 1024*1024);
4673         size = bound(65536, size, 512*1024*1024);
4674         if (!mem || mem->size != size || mustgrow)
4675         {
4676                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4677                 mem->size = size;
4678                 mem->current = 0;
4679                 if (type == R_BUFFERDATA_VERTEX)
4680                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4681                 else if (type == R_BUFFERDATA_INDEX16)
4682                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4683                 else if (type == R_BUFFERDATA_INDEX32)
4684                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4685                 else if (type == R_BUFFERDATA_UNIFORM)
4686                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4687                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4688                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4689         }
4690 }
4691
4692 void R_BufferData_NewFrame(void)
4693 {
4694         int type;
4695         r_bufferdata_buffer_t **p, *mem;
4696         // cycle to the next frame's buffers
4697         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4698         // if we ran out of space on the last time we used these buffers, free the old memory now
4699         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4700         {
4701                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4702                 {
4703                         R_BufferData_Resize(type, false);
4704                         // free all but the head buffer, this is how we recycle obsolete
4705                         // buffers after they are no longer in use
4706                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4707                         while (*p)
4708                         {
4709                                 mem = *p;
4710                                 *p = (*p)->purge;
4711                                 if (mem->buffer)
4712                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4713                                 Mem_Free(mem);
4714                         }
4715                         // reset the current offset
4716                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4717                 }
4718         }
4719 }
4720
4721 r_meshbuffer_t *R_BufferData_Store(size_t datasize, void *data, r_bufferdata_type_t type, int *returnbufferoffset, qboolean allowfail)
4722 {
4723         r_bufferdata_buffer_t *mem;
4724         int offset = 0;
4725         int padsize;
4726         float newvalue;
4727
4728         *returnbufferoffset = 0;
4729
4730         // align size to a byte boundary appropriate for the buffer type, this
4731         // makes all allocations have aligned start offsets
4732         if (type == R_BUFFERDATA_UNIFORM)
4733                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4734         else
4735                 padsize = (datasize + 15) & ~15;
4736
4737         while (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4738         {
4739                 // emergency - we ran out of space, allocate more memory
4740                 newvalue = bound(0.25f, r_bufferdatasize[type].value * 2.0f, 256.0f);
4741                 // if we're already at the limit, just fail (if allowfail is false we might run out of video ram)
4742                 if (newvalue == r_bufferdatasize[type].value && allowfail)
4743                         return NULL;
4744                 Cvar_SetValueQuick(&r_bufferdatasize[type], newvalue);
4745                 R_BufferData_Resize(type, true);
4746         }
4747
4748         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4749         offset = mem->current;
4750         mem->current += padsize;
4751
4752         // upload the data to the buffer at the chosen offset
4753         if (offset == 0)
4754                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4755         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4756
4757         // count the usage for stats
4758         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4759         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4760
4761         // return the buffer offset
4762         *returnbufferoffset = offset;
4763
4764         return mem->buffer;
4765 }
4766
4767 //==================================================================================
4768
4769 // LordHavoc: animcache originally written by Echon, rewritten since then
4770
4771 /**
4772  * Animation cache prevents re-generating mesh data for an animated model
4773  * multiple times in one frame for lighting, shadowing, reflections, etc.
4774  */
4775
4776 void R_AnimCache_Free(void)
4777 {
4778 }
4779
4780 void R_AnimCache_ClearCache(void)
4781 {
4782         int i;
4783         entity_render_t *ent;
4784
4785         for (i = 0;i < r_refdef.scene.numentities;i++)
4786         {
4787                 ent = r_refdef.scene.entities[i];
4788                 ent->animcache_vertex3f = NULL; // for shadow geometry
4789                 ent->animcache_normal3f = NULL; // for lit geometry
4790                 ent->animcache_svector3f = NULL; // for lit geometry
4791                 ent->animcache_tvector3f = NULL; // for lit geometry
4792                 ent->animcache_vertexmesh = NULL; // interleaved vertex arrays for D3D
4793                 ent->animcache_vertex3fbuffer = NULL; // vertex buffer for D3D
4794                 ent->animcache_vertexmeshbuffer = NULL; // vertex buffer for D3D
4795                 ent->animcache_skeletaltransform3x4 = NULL; // for dynamic batch fallback with r_glsl_skeletal
4796                 ent->animcache_skeletaltransform3x4buffer = NULL; // for r_glsl_skeletal
4797                 ent->animcache_skeletaltransform3x4offset = 0;
4798                 ent->animcache_skeletaltransform3x4size = 0;
4799         }
4800 }
4801
4802 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4803 {
4804         int i;
4805
4806         // check if we need the meshbuffers
4807         if (!vid.useinterleavedarrays)
4808                 return;
4809
4810         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4811                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4812         // TODO: upload vertex3f buffer?
4813         if (ent->animcache_vertexmesh)
4814         {
4815                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4816                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4817                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4818                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4819                 for (i = 0;i < numvertices;i++)
4820                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4821                 if (ent->animcache_svector3f)
4822                         for (i = 0;i < numvertices;i++)
4823                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4824                 if (ent->animcache_tvector3f)
4825                         for (i = 0;i < numvertices;i++)
4826                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4827                 if (ent->animcache_normal3f)
4828                         for (i = 0;i < numvertices;i++)
4829                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4830                 // TODO: upload vertexmeshbuffer?
4831         }
4832 }
4833
4834 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4835 {
4836         dp_model_t *model = ent->model;
4837         int numvertices;
4838
4839         // see if this ent is worth caching
4840         if (!model || !model->Draw || !model->AnimateVertices)
4841                 return false;
4842         // nothing to cache if it contains no animations and has no skeleton
4843         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4844                 return false;
4845         // see if it is already cached for gpuskeletal
4846         if (ent->animcache_skeletaltransform3x4)
4847                 return false;
4848         // see if it is already cached as a mesh
4849         if (ent->animcache_vertex3f)
4850         {
4851                 // check if we need to add normals or tangents
4852                 if (ent->animcache_normal3f)
4853                         wantnormals = false;
4854                 if (ent->animcache_svector3f)
4855                         wanttangents = false;
4856                 if (!wantnormals && !wanttangents)
4857                         return false;
4858         }
4859
4860         // check which kind of cache we need to generate
4861         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4862         {
4863                 // cache the skeleton so the vertex shader can use it
4864                 int i;
4865                 int blends;
4866                 const skeleton_t *skeleton = ent->skeleton;
4867                 const frameblend_t *frameblend = ent->frameblend;
4868                 float *boneposerelative;
4869                 float m[12];
4870                 static float bonepose[256][12];
4871                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4872                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4873                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4874                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4875                 boneposerelative = ent->animcache_skeletaltransform3x4;
4876                 if (skeleton && !skeleton->relativetransforms)
4877                         skeleton = NULL;
4878                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4879                 if (skeleton)
4880                 {
4881                         for (i = 0;i < model->num_bones;i++)
4882                         {
4883                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4884                                 if (model->data_bones[i].parent >= 0)
4885                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4886                                 else
4887                                         memcpy(bonepose[i], m, sizeof(m));
4888
4889                                 // create a relative deformation matrix to describe displacement
4890                                 // from the base mesh, which is used by the actual weighting
4891                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4892                         }
4893                 }
4894                 else
4895                 {
4896                         for (i = 0;i < model->num_bones;i++)
4897                         {
4898                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4899                                 float lerp = frameblend[0].lerp,
4900                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4901                                         rx = pose7s[3] * lerp,
4902                                         ry = pose7s[4] * lerp,
4903                                         rz = pose7s[5] * lerp,
4904                                         rw = pose7s[6] * lerp,
4905                                         dx = tx*rw + ty*rz - tz*ry,
4906                                         dy = -tx*rz + ty*rw + tz*rx,
4907                                         dz = tx*ry - ty*rx + tz*rw,
4908                                         dw = -tx*rx - ty*ry - tz*rz,
4909                                         scale, sx, sy, sz, sw;
4910                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4911                                 {
4912                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4913                                         float lerp = frameblend[blends].lerp,
4914                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4915                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4916                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4917                                         qx *= lerp;
4918                                         qy *= lerp;
4919                                         qz *= lerp;
4920                                         qw *= lerp;
4921                                         rx += qx;
4922                                         ry += qy;
4923                                         rz += qz;
4924                                         rw += qw;
4925                                         dx += tx*qw + ty*qz - tz*qy;
4926                                         dy += -tx*qz + ty*qw + tz*qx;
4927                                         dz += tx*qy - ty*qx + tz*qw;
4928                                         dw += -tx*qx - ty*qy - tz*qz;
4929                                 }
4930                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4931                                 sx = rx * scale;
4932                                 sy = ry * scale;
4933                                 sz = rz * scale;
4934                                 sw = rw * scale;
4935                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4936                                 m[1] = 2*(sx*ry - sw*rz);
4937                                 m[2] = 2*(sx*rz + sw*ry);
4938                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4939                                 m[4] = 2*(sx*ry + sw*rz);
4940                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4941                                 m[6] = 2*(sy*rz - sw*rx);
4942                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4943                                 m[8] = 2*(sx*rz - sw*ry);
4944                                 m[9] = 2*(sy*rz + sw*rx);
4945                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4946                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4947                                 if (i == r_skeletal_debugbone.integer)
4948                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4949                                 m[3] *= r_skeletal_debugtranslatex.value;
4950                                 m[7] *= r_skeletal_debugtranslatey.value;
4951                                 m[11] *= r_skeletal_debugtranslatez.value;
4952                                 if (model->data_bones[i].parent >= 0)
4953                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4954                                 else
4955                                         memcpy(bonepose[i], m, sizeof(m));
4956                                 // create a relative deformation matrix to describe displacement
4957                                 // from the base mesh, which is used by the actual weighting
4958                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4959                         }
4960                 }
4961                 // note: this can fail if the buffer is at the grow limit
4962                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4963                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset, true);
4964         }
4965         else if (ent->animcache_vertex3f)
4966         {
4967                 // mesh was already cached but we may need to add normals/tangents
4968                 // (this only happens with multiple views, reflections, cameras, etc)
4969                 if (wantnormals || wanttangents)
4970                 {
4971                         numvertices = model->surfmesh.num_vertices;
4972                         if (wantnormals)
4973                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4974                         if (wanttangents)
4975                         {
4976                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4977                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978                         }
4979                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4980                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4981                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4982                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4983                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4984                 }
4985         }
4986         else
4987         {
4988                 // generate mesh cache
4989                 numvertices = model->surfmesh.num_vertices;
4990                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4991                 if (wantnormals)
4992                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4993                 if (wanttangents)
4994                 {
4995                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4996                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4997                 }
4998                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4999                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5000                 if (wantnormals || wanttangents)
5001                 {
5002                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5003                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5004                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5005                 }
5006                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5007                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5008                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5009         }
5010         return true;
5011 }
5012
5013 void R_AnimCache_CacheVisibleEntities(void)
5014 {
5015         int i;
5016         qboolean wantnormals = true;
5017         qboolean wanttangents = !r_showsurfaces.integer;
5018
5019         switch(vid.renderpath)
5020         {
5021         case RENDERPATH_GL20:
5022         case RENDERPATH_D3D9:
5023         case RENDERPATH_D3D10:
5024         case RENDERPATH_D3D11:
5025         case RENDERPATH_GLES2:
5026                 break;
5027         case RENDERPATH_GL11:
5028         case RENDERPATH_GL13:
5029         case RENDERPATH_GLES1:
5030                 wanttangents = false;
5031                 break;
5032         case RENDERPATH_SOFT:
5033                 break;
5034         }
5035
5036         if (r_shownormals.integer)
5037                 wanttangents = wantnormals = true;
5038
5039         // TODO: thread this
5040         // NOTE: R_PrepareRTLights() also caches entities
5041
5042         for (i = 0;i < r_refdef.scene.numentities;i++)
5043                 if (r_refdef.viewcache.entityvisible[i])
5044                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5045 }
5046
5047 //==================================================================================
5048
5049 extern cvar_t r_overheadsprites_pushback;
5050
5051 static void R_View_UpdateEntityLighting (void)
5052 {
5053         int i;
5054         entity_render_t *ent;
5055         vec3_t tempdiffusenormal, avg;
5056         vec_t f, fa, fd, fdd;
5057         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5058
5059         for (i = 0;i < r_refdef.scene.numentities;i++)
5060         {
5061                 ent = r_refdef.scene.entities[i];
5062
5063                 // skip unseen models
5064                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5065                         continue;
5066
5067                 // skip bsp models
5068                 if (ent->model && ent->model == cl.worldmodel)
5069                 {
5070                         // TODO: use modellight for r_ambient settings on world?
5071                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5072                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5073                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5074                         continue;
5075                 }
5076                 
5077                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5078                 {
5079                         // aleady updated by CSQC
5080                         // TODO: force modellight on BSP models in this case?
5081                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5082                 }
5083                 else
5084                 {
5085                         // fetch the lighting from the worldmodel data
5086                         VectorClear(ent->modellight_ambient);
5087                         VectorClear(ent->modellight_diffuse);
5088                         VectorClear(tempdiffusenormal);
5089                         if (ent->flags & RENDER_LIGHT)
5090                         {
5091                                 vec3_t org;
5092                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5093
5094                                 // complete lightning for lit sprites
5095                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5096                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5097                                 {
5098                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5099                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5100                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5101                                 }
5102                                 else
5103                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5104
5105                                 if(ent->flags & RENDER_EQUALIZE)
5106                                 {
5107                                         // first fix up ambient lighting...
5108                                         if(r_equalize_entities_minambient.value > 0)
5109                                         {
5110                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5111                                                 if(fd > 0)
5112                                                 {
5113                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5114                                                         if(fa < r_equalize_entities_minambient.value * fd)
5115                                                         {
5116                                                                 // solve:
5117                                                                 //   fa'/fd' = minambient
5118                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5119                                                                 //   ...
5120                                                                 //   fa' = fd' * minambient
5121                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5122                                                                 //   ...
5123                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5124                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5125                                                                 //   ...
5126                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5127                                                                 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
5128                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5129                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5130                                                         }
5131                                                 }
5132                                         }
5133
5134                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5135                                         {
5136                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5137                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5138                                                 f = fa + 0.25 * fd;
5139                                                 if(f > 0)
5140                                                 {
5141                                                         // adjust brightness and saturation to target
5142                                                         avg[0] = avg[1] = avg[2] = fa / f;
5143                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5144                                                         avg[0] = avg[1] = avg[2] = fd / f;
5145                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5146                                                 }
5147                                         }
5148                                 }
5149                         }
5150                         else // highly rare
5151                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5152                 }
5153
5154                 // move the light direction into modelspace coordinates for lighting code
5155                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5156                 if(VectorLength2(ent->modellight_lightdir) == 0)
5157                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5158                 VectorNormalize(ent->modellight_lightdir);
5159         }
5160 }
5161
5162 #define MAX_LINEOFSIGHTTRACES 64
5163
5164 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5165 {
5166         int i;
5167         vec3_t boxmins, boxmaxs;
5168         vec3_t start;
5169         vec3_t end;
5170         dp_model_t *model = r_refdef.scene.worldmodel;
5171
5172         if (!model || !model->brush.TraceLineOfSight)
5173                 return true;
5174
5175         // expand the box a little
5176         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5177         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5178         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5179         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5180         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5181         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5182
5183         // return true if eye is inside enlarged box
5184         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5185                 return true;
5186
5187         // try center
5188         VectorCopy(eye, start);
5189         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5190         if (model->brush.TraceLineOfSight(model, start, end))
5191                 return true;
5192
5193         // try various random positions
5194         for (i = 0;i < numsamples;i++)
5195         {
5196                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5197                 if (model->brush.TraceLineOfSight(model, start, end))
5198                         return true;
5199         }
5200
5201         return false;
5202 }
5203
5204
5205 static void R_View_UpdateEntityVisible (void)
5206 {
5207         int i;
5208         int renderimask;
5209         int samples;
5210         entity_render_t *ent;
5211
5212         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5213                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5214                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5215                 :                                                          RENDER_EXTERIORMODEL;
5216         if (!r_drawviewmodel.integer)
5217                 renderimask |= RENDER_VIEWMODEL;
5218         if (!r_drawexteriormodel.integer)
5219                 renderimask |= RENDER_EXTERIORMODEL;
5220         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5221         {
5222                 // worldmodel can check visibility
5223                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5224                 for (i = 0;i < r_refdef.scene.numentities;i++)
5225                 {
5226                         ent = r_refdef.scene.entities[i];
5227                         if (!(ent->flags & renderimask))
5228                         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)))
5229                         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))
5230                                 r_refdef.viewcache.entityvisible[i] = true;
5231                 }
5232         }
5233         else
5234         {
5235                 // no worldmodel or it can't check visibility
5236                 for (i = 0;i < r_refdef.scene.numentities;i++)
5237                 {
5238                         ent = r_refdef.scene.entities[i];
5239                         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));
5240                 }
5241         }
5242         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5243                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5244         {
5245                 for (i = 0;i < r_refdef.scene.numentities;i++)
5246                 {
5247                         if (!r_refdef.viewcache.entityvisible[i])
5248                                 continue;
5249                         ent = r_refdef.scene.entities[i];
5250                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5251                         {
5252                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5253                                 if (samples < 0)
5254                                         continue; // temp entities do pvs only
5255                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5256                                         ent->last_trace_visibility = realtime;
5257                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5258                                         r_refdef.viewcache.entityvisible[i] = 0;
5259                         }
5260                 }
5261         }
5262 }
5263
5264 /// only used if skyrendermasked, and normally returns false
5265 static int R_DrawBrushModelsSky (void)
5266 {
5267         int i, sky;
5268         entity_render_t *ent;
5269
5270         sky = false;
5271         for (i = 0;i < r_refdef.scene.numentities;i++)
5272         {
5273                 if (!r_refdef.viewcache.entityvisible[i])
5274                         continue;
5275                 ent = r_refdef.scene.entities[i];
5276                 if (!ent->model || !ent->model->DrawSky)
5277                         continue;
5278                 ent->model->DrawSky(ent);
5279                 sky = true;
5280         }
5281         return sky;
5282 }
5283
5284 static void R_DrawNoModel(entity_render_t *ent);
5285 static void R_DrawModels(void)
5286 {
5287         int i;
5288         entity_render_t *ent;
5289
5290         for (i = 0;i < r_refdef.scene.numentities;i++)
5291         {
5292                 if (!r_refdef.viewcache.entityvisible[i])
5293                         continue;
5294                 ent = r_refdef.scene.entities[i];
5295                 r_refdef.stats[r_stat_entities]++;
5296                 /*
5297                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5298                 {
5299                         vec3_t f, l, u, o;
5300                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5301                         Con_Printf("R_DrawModels\n");
5302                         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]);
5303                         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);
5304                         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);
5305                 }
5306                 */
5307                 if (ent->model && ent->model->Draw != NULL)
5308                         ent->model->Draw(ent);
5309                 else
5310                         R_DrawNoModel(ent);
5311         }
5312 }
5313
5314 static void R_DrawModelsDepth(void)
5315 {
5316         int i;
5317         entity_render_t *ent;
5318
5319         for (i = 0;i < r_refdef.scene.numentities;i++)
5320         {
5321                 if (!r_refdef.viewcache.entityvisible[i])
5322                         continue;
5323                 ent = r_refdef.scene.entities[i];
5324                 if (ent->model && ent->model->DrawDepth != NULL)
5325                         ent->model->DrawDepth(ent);
5326         }
5327 }
5328
5329 static void R_DrawModelsDebug(void)
5330 {
5331         int i;
5332         entity_render_t *ent;
5333
5334         for (i = 0;i < r_refdef.scene.numentities;i++)
5335         {
5336                 if (!r_refdef.viewcache.entityvisible[i])
5337                         continue;
5338                 ent = r_refdef.scene.entities[i];
5339                 if (ent->model && ent->model->DrawDebug != NULL)
5340                         ent->model->DrawDebug(ent);
5341         }
5342 }
5343
5344 static void R_DrawModelsAddWaterPlanes(void)
5345 {
5346         int i;
5347         entity_render_t *ent;
5348
5349         for (i = 0;i < r_refdef.scene.numentities;i++)
5350         {
5351                 if (!r_refdef.viewcache.entityvisible[i])
5352                         continue;
5353                 ent = r_refdef.scene.entities[i];
5354                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5355                         ent->model->DrawAddWaterPlanes(ent);
5356         }
5357 }
5358
5359 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}};
5360
5361 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5362 {
5363         if (r_hdr_irisadaptation.integer)
5364         {
5365                 vec3_t p;
5366                 vec3_t ambient;
5367                 vec3_t diffuse;
5368                 vec3_t diffusenormal;
5369                 vec3_t forward;
5370                 vec_t brightness = 0.0f;
5371                 vec_t goal;
5372                 vec_t current;
5373                 vec_t d;
5374                 int c;
5375                 VectorCopy(r_refdef.view.forward, forward);
5376                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5377                 {
5378                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5379                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5380                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5381                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5382                         d = DotProduct(forward, diffusenormal);
5383                         brightness += VectorLength(ambient);
5384                         if (d > 0)
5385                                 brightness += d * VectorLength(diffuse);
5386                 }
5387                 brightness *= 1.0f / c;
5388                 brightness += 0.00001f; // make sure it's never zero
5389                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5390                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5391                 current = r_hdr_irisadaptation_value.value;
5392                 if (current < goal)
5393                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5394                 else if (current > goal)
5395                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5396                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5397                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5398         }
5399         else if (r_hdr_irisadaptation_value.value != 1.0f)
5400                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5401 }
5402
5403 static void R_View_SetFrustum(const int *scissor)
5404 {
5405         int i;
5406         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5407         vec3_t forward, left, up, origin, v;
5408
5409         if(scissor)
5410         {
5411                 // flipped x coordinates (because x points left here)
5412                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5413                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5414
5415                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5416                 switch(vid.renderpath)
5417                 {
5418                         case RENDERPATH_D3D9:
5419                         case RENDERPATH_D3D10:
5420                         case RENDERPATH_D3D11:
5421                                 // non-flipped y coordinates
5422                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5423                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5424                                 break;
5425                         case RENDERPATH_SOFT:
5426                         case RENDERPATH_GL11:
5427                         case RENDERPATH_GL13:
5428                         case RENDERPATH_GL20:
5429                         case RENDERPATH_GLES1:
5430                         case RENDERPATH_GLES2:
5431                                 // non-flipped y coordinates
5432                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5433                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5434                                 break;
5435                 }
5436         }
5437
5438         // we can't trust r_refdef.view.forward and friends in reflected scenes
5439         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5440
5441 #if 0
5442         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5443         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5444         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5445         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5446         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5447         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5448         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5449         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5450         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5451         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5452         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5453         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5454 #endif
5455
5456 #if 0
5457         zNear = r_refdef.nearclip;
5458         nudge = 1.0 - 1.0 / (1<<23);
5459         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5460         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5461         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5462         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5463         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5464         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5465         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5466         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5467 #endif
5468
5469
5470
5471 #if 0
5472         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5473         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5474         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5475         r_refdef.view.frustum[0].dist = m[15] - m[12];
5476
5477         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5478         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5479         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5480         r_refdef.view.frustum[1].dist = m[15] + m[12];
5481
5482         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5483         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5484         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5485         r_refdef.view.frustum[2].dist = m[15] - m[13];
5486
5487         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5488         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5489         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5490         r_refdef.view.frustum[3].dist = m[15] + m[13];
5491
5492         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5493         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5494         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5495         r_refdef.view.frustum[4].dist = m[15] - m[14];
5496
5497         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5498         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5499         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5500         r_refdef.view.frustum[5].dist = m[15] + m[14];
5501 #endif
5502
5503         if (r_refdef.view.useperspective)
5504         {
5505                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5506                 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]);
5507                 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]);
5508                 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]);
5509                 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]);
5510
5511                 // then the normals from the corners relative to origin
5512                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5513                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5514                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5515                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5516
5517                 // in a NORMAL view, forward cross left == up
5518                 // in a REFLECTED view, forward cross left == down
5519                 // so our cross products above need to be adjusted for a left handed coordinate system
5520                 CrossProduct(forward, left, v);
5521                 if(DotProduct(v, up) < 0)
5522                 {
5523                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5524                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5525                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5526                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5527                 }
5528
5529                 // Leaving those out was a mistake, those were in the old code, and they
5530                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5531                 // I couldn't reproduce it after adding those normalizations. --blub
5532                 VectorNormalize(r_refdef.view.frustum[0].normal);
5533                 VectorNormalize(r_refdef.view.frustum[1].normal);
5534                 VectorNormalize(r_refdef.view.frustum[2].normal);
5535                 VectorNormalize(r_refdef.view.frustum[3].normal);
5536
5537                 // make the corners absolute
5538                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5539                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5540                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5541                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5542
5543                 // one more normal
5544                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5545
5546                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5547                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5548                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5549                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5550                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5551         }
5552         else
5553         {
5554                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5555                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5556                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5557                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5558                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5559                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5560                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5561                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5562                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5563                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5564         }
5565         r_refdef.view.numfrustumplanes = 5;
5566
5567         if (r_refdef.view.useclipplane)
5568         {
5569                 r_refdef.view.numfrustumplanes = 6;
5570                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5571         }
5572
5573         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5574                 PlaneClassify(r_refdef.view.frustum + i);
5575
5576         // LordHavoc: note to all quake engine coders, Quake had a special case
5577         // for 90 degrees which assumed a square view (wrong), so I removed it,
5578         // Quake2 has it disabled as well.
5579
5580         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5581         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5582         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5583         //PlaneClassify(&frustum[0]);
5584
5585         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5586         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5587         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5588         //PlaneClassify(&frustum[1]);
5589
5590         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5591         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5592         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5593         //PlaneClassify(&frustum[2]);
5594
5595         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5596         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5597         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5598         //PlaneClassify(&frustum[3]);
5599
5600         // nearclip plane
5601         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5602         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5603         //PlaneClassify(&frustum[4]);
5604 }
5605
5606 static void R_View_UpdateWithScissor(const int *myscissor)
5607 {
5608         R_Main_ResizeViewCache();
5609         R_View_SetFrustum(myscissor);
5610         R_View_WorldVisibility(r_refdef.view.useclipplane);
5611         R_View_UpdateEntityVisible();
5612         R_View_UpdateEntityLighting();
5613 }
5614
5615 static void R_View_Update(void)
5616 {
5617         R_Main_ResizeViewCache();
5618         R_View_SetFrustum(NULL);
5619         R_View_WorldVisibility(r_refdef.view.useclipplane);
5620         R_View_UpdateEntityVisible();
5621         R_View_UpdateEntityLighting();
5622 }
5623
5624 float viewscalefpsadjusted = 1.0f;
5625
5626 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5627 {
5628         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5629         scale = bound(0.03125f, scale, 1.0f);
5630         *outwidth = (int)ceil(width * scale);
5631         *outheight = (int)ceil(height * scale);
5632 }
5633
5634 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5635 {
5636         const float *customclipplane = NULL;
5637         float plane[4];
5638         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5639         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5640         {
5641                 // LordHavoc: couldn't figure out how to make this approach the
5642                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5643                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5644                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5645                         dist = r_refdef.view.clipplane.dist;
5646                 plane[0] = r_refdef.view.clipplane.normal[0];
5647                 plane[1] = r_refdef.view.clipplane.normal[1];
5648                 plane[2] = r_refdef.view.clipplane.normal[2];
5649                 plane[3] = -dist;
5650                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5651         }
5652
5653         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5654         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5655
5656         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5657         if (!r_refdef.view.useperspective)
5658                 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);
5659         else if (vid.stencil && r_useinfinitefarclip.integer)
5660                 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);
5661         else
5662                 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);
5663         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5664         R_SetViewport(&r_refdef.view.viewport);
5665         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5666         {
5667                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5668                 float screenplane[4];
5669                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5670                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5671                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5672                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5673                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5674         }
5675 }
5676
5677 void R_EntityMatrix(const matrix4x4_t *matrix)
5678 {
5679         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5680         {
5681                 gl_modelmatrixchanged = false;
5682                 gl_modelmatrix = *matrix;
5683                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5684                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5685                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5686                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5687                 CHECKGLERROR
5688                 switch(vid.renderpath)
5689                 {
5690                 case RENDERPATH_D3D9:
5691 #ifdef SUPPORTD3D
5692                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5693                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5694 #endif
5695                         break;
5696                 case RENDERPATH_D3D10:
5697                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5698                         break;
5699                 case RENDERPATH_D3D11:
5700                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5701                         break;
5702                 case RENDERPATH_GL11:
5703                 case RENDERPATH_GL13:
5704                 case RENDERPATH_GLES1:
5705                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5706                         break;
5707                 case RENDERPATH_SOFT:
5708                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5709                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5710                         break;
5711                 case RENDERPATH_GL20:
5712                 case RENDERPATH_GLES2:
5713                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5714                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5715                         break;
5716                 }
5717         }
5718 }
5719
5720 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5721 {
5722         r_viewport_t viewport;
5723
5724         CHECKGLERROR
5725
5726         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5727         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);
5728         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5729         R_SetViewport(&viewport);
5730         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5731         GL_Color(1, 1, 1, 1);
5732         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5733         GL_BlendFunc(GL_ONE, GL_ZERO);
5734         GL_ScissorTest(false);
5735         GL_DepthMask(false);
5736         GL_DepthRange(0, 1);
5737         GL_DepthTest(false);
5738         GL_DepthFunc(GL_LEQUAL);
5739         R_EntityMatrix(&identitymatrix);
5740         R_Mesh_ResetTextureState();
5741         GL_PolygonOffset(0, 0);
5742         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5743         switch(vid.renderpath)
5744         {
5745         case RENDERPATH_GL11:
5746         case RENDERPATH_GL13:
5747         case RENDERPATH_GL20:
5748         case RENDERPATH_GLES1:
5749         case RENDERPATH_GLES2:
5750                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5751                 break;
5752         case RENDERPATH_D3D9:
5753         case RENDERPATH_D3D10:
5754         case RENDERPATH_D3D11:
5755         case RENDERPATH_SOFT:
5756                 break;
5757         }
5758         GL_CullFace(GL_NONE);
5759
5760         CHECKGLERROR
5761 }
5762
5763 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5764 {
5765         DrawQ_Finish();
5766
5767         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5768 }
5769
5770 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5771 {
5772         DrawQ_Finish();
5773
5774         R_SetupView(true, fbo, depthtexture, colortexture);
5775         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5776         GL_Color(1, 1, 1, 1);
5777         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5778         GL_BlendFunc(GL_ONE, GL_ZERO);
5779         GL_ScissorTest(true);
5780         GL_DepthMask(true);
5781         GL_DepthRange(0, 1);
5782         GL_DepthTest(true);
5783         GL_DepthFunc(GL_LEQUAL);
5784         R_EntityMatrix(&identitymatrix);
5785         R_Mesh_ResetTextureState();
5786         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5787         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5788         switch(vid.renderpath)
5789         {
5790         case RENDERPATH_GL11:
5791         case RENDERPATH_GL13:
5792         case RENDERPATH_GL20:
5793         case RENDERPATH_GLES1:
5794         case RENDERPATH_GLES2:
5795                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5796                 break;
5797         case RENDERPATH_D3D9:
5798         case RENDERPATH_D3D10:
5799         case RENDERPATH_D3D11:
5800         case RENDERPATH_SOFT:
5801                 break;
5802         }
5803         GL_CullFace(r_refdef.view.cullface_back);
5804 }
5805
5806 /*
5807 ================
5808 R_RenderView_UpdateViewVectors
5809 ================
5810 */
5811 void R_RenderView_UpdateViewVectors(void)
5812 {
5813         // break apart the view matrix into vectors for various purposes
5814         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5815         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5816         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5817         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5818         // make an inverted copy of the view matrix for tracking sprites
5819         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5820 }
5821
5822 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5823 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5824
5825 static void R_Water_StartFrame(void)
5826 {
5827         int i;
5828         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5829         r_waterstate_waterplane_t *p;
5830         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;
5831
5832         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5833                 return;
5834
5835         switch(vid.renderpath)
5836         {
5837         case RENDERPATH_GL20:
5838         case RENDERPATH_D3D9:
5839         case RENDERPATH_D3D10:
5840         case RENDERPATH_D3D11:
5841         case RENDERPATH_SOFT:
5842         case RENDERPATH_GLES2:
5843                 break;
5844         case RENDERPATH_GL11:
5845         case RENDERPATH_GL13:
5846         case RENDERPATH_GLES1:
5847                 return;
5848         }
5849
5850         // set waterwidth and waterheight to the water resolution that will be
5851         // used (often less than the screen resolution for faster rendering)
5852         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5853
5854         // calculate desired texture sizes
5855         // can't use water if the card does not support the texture size
5856         if (!r_water.integer || r_showsurfaces.integer)
5857                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5858         else if (vid.support.arb_texture_non_power_of_two)
5859         {
5860                 texturewidth = waterwidth;
5861                 textureheight = waterheight;
5862                 camerawidth = waterwidth;
5863                 cameraheight = waterheight;
5864         }
5865         else
5866         {
5867                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5868                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5869                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5870                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5871         }
5872
5873         // allocate textures as needed
5874         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))
5875         {
5876                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5877                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5878                 {
5879                         if (p->texture_refraction)
5880                                 R_FreeTexture(p->texture_refraction);
5881                         p->texture_refraction = NULL;
5882                         if (p->fbo_refraction)
5883                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5884                         p->fbo_refraction = 0;
5885                         if (p->texture_reflection)
5886                                 R_FreeTexture(p->texture_reflection);
5887                         p->texture_reflection = NULL;
5888                         if (p->fbo_reflection)
5889                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5890                         p->fbo_reflection = 0;
5891                         if (p->texture_camera)
5892                                 R_FreeTexture(p->texture_camera);
5893                         p->texture_camera = NULL;
5894                         if (p->fbo_camera)
5895                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5896                         p->fbo_camera = 0;
5897                 }
5898                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5899                 r_fb.water.texturewidth = texturewidth;
5900                 r_fb.water.textureheight = textureheight;
5901                 r_fb.water.camerawidth = camerawidth;
5902                 r_fb.water.cameraheight = cameraheight;
5903         }
5904
5905         if (r_fb.water.texturewidth)
5906         {
5907                 int scaledwidth, scaledheight;
5908
5909                 r_fb.water.enabled = true;
5910
5911                 // water resolution is usually reduced
5912                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5913                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5914                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5915
5916                 // set up variables that will be used in shader setup
5917                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5918                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5919                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5920                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5921         }
5922
5923         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5924         r_fb.water.numwaterplanes = 0;
5925 }
5926
5927 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5928 {
5929         int planeindex, bestplaneindex, vertexindex;
5930         vec3_t mins, maxs, normal, center, v, n;
5931         vec_t planescore, bestplanescore;
5932         mplane_t plane;
5933         r_waterstate_waterplane_t *p;
5934         texture_t *t = R_GetCurrentTexture(surface->texture);
5935
5936         rsurface.texture = t;
5937         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5938         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5939         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5940                 return;
5941         // average the vertex normals, find the surface bounds (after deformvertexes)
5942         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5943         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5944         VectorCopy(n, normal);
5945         VectorCopy(v, mins);
5946         VectorCopy(v, maxs);
5947         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5948         {
5949                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5950                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5951                 VectorAdd(normal, n, normal);
5952                 mins[0] = min(mins[0], v[0]);
5953                 mins[1] = min(mins[1], v[1]);
5954                 mins[2] = min(mins[2], v[2]);
5955                 maxs[0] = max(maxs[0], v[0]);
5956                 maxs[1] = max(maxs[1], v[1]);
5957                 maxs[2] = max(maxs[2], v[2]);
5958         }
5959         VectorNormalize(normal);
5960         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5961
5962         VectorCopy(normal, plane.normal);
5963         VectorNormalize(plane.normal);
5964         plane.dist = DotProduct(center, plane.normal);
5965         PlaneClassify(&plane);
5966         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5967         {
5968                 // skip backfaces (except if nocullface is set)
5969 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5970 //                      return;
5971                 VectorNegate(plane.normal, plane.normal);
5972                 plane.dist *= -1;
5973                 PlaneClassify(&plane);
5974         }
5975
5976
5977         // find a matching plane if there is one
5978         bestplaneindex = -1;
5979         bestplanescore = 1048576.0f;
5980         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5981         {
5982                 if(p->camera_entity == t->camera_entity)
5983                 {
5984                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5985                         if (bestplaneindex < 0 || bestplanescore > planescore)
5986                         {
5987                                 bestplaneindex = planeindex;
5988                                 bestplanescore = planescore;
5989                         }
5990                 }
5991         }
5992         planeindex = bestplaneindex;
5993         p = r_fb.water.waterplanes + planeindex;
5994
5995         // if this surface does not fit any known plane rendered this frame, add one
5996         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5997         {
5998                 // store the new plane
5999                 planeindex = r_fb.water.numwaterplanes++;
6000                 p = r_fb.water.waterplanes + planeindex;
6001                 p->plane = plane;
6002                 // clear materialflags and pvs
6003                 p->materialflags = 0;
6004                 p->pvsvalid = false;
6005                 p->camera_entity = t->camera_entity;
6006                 VectorCopy(mins, p->mins);
6007                 VectorCopy(maxs, p->maxs);
6008         }
6009         else
6010         {
6011                 // merge mins/maxs when we're adding this surface to the plane
6012                 p->mins[0] = min(p->mins[0], mins[0]);
6013                 p->mins[1] = min(p->mins[1], mins[1]);
6014                 p->mins[2] = min(p->mins[2], mins[2]);
6015                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6016                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6017                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6018         }
6019         // merge this surface's materialflags into the waterplane
6020         p->materialflags |= t->currentmaterialflags;
6021         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6022         {
6023                 // merge this surface's PVS into the waterplane
6024                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6025                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6026                 {
6027                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6028                         p->pvsvalid = true;
6029                 }
6030         }
6031 }
6032
6033 extern cvar_t r_drawparticles;
6034 extern cvar_t r_drawdecals;
6035
6036 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6037 {
6038         int myscissor[4];
6039         r_refdef_view_t originalview;
6040         r_refdef_view_t myview;
6041         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;
6042         r_waterstate_waterplane_t *p;
6043         vec3_t visorigin;
6044         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;
6045         char vabuf[1024];
6046
6047         originalview = r_refdef.view;
6048
6049         // lowquality hack, temporarily shut down some cvars and restore afterwards
6050         qualityreduction = r_water_lowquality.integer;
6051         if (qualityreduction > 0)
6052         {
6053                 if (qualityreduction >= 1)
6054                 {
6055                         old_r_shadows = r_shadows.integer;
6056                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6057                         old_r_dlight = r_shadow_realtime_dlight.integer;
6058                         Cvar_SetValueQuick(&r_shadows, 0);
6059                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6060                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6061                 }
6062                 if (qualityreduction >= 2)
6063                 {
6064                         old_r_dynamic = r_dynamic.integer;
6065                         old_r_particles = r_drawparticles.integer;
6066                         old_r_decals = r_drawdecals.integer;
6067                         Cvar_SetValueQuick(&r_dynamic, 0);
6068                         Cvar_SetValueQuick(&r_drawparticles, 0);
6069                         Cvar_SetValueQuick(&r_drawdecals, 0);
6070                 }
6071         }
6072
6073         // make sure enough textures are allocated
6074         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6075         {
6076                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6077                 {
6078                         if (!p->texture_refraction)
6079                                 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);
6080                         if (!p->texture_refraction)
6081                                 goto error;
6082                         if (usewaterfbo)
6083                         {
6084                                 if (r_fb.water.depthtexture == NULL)
6085                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6086                                 if (p->fbo_refraction == 0)
6087                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6088                         }
6089                 }
6090                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6091                 {
6092                         if (!p->texture_camera)
6093                                 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);
6094                         if (!p->texture_camera)
6095                                 goto error;
6096                         if (usewaterfbo)
6097                         {
6098                                 if (r_fb.water.depthtexture == NULL)
6099                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6100                                 if (p->fbo_camera == 0)
6101                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6102                         }
6103                 }
6104
6105                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6106                 {
6107                         if (!p->texture_reflection)
6108                                 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);
6109                         if (!p->texture_reflection)
6110                                 goto error;
6111                         if (usewaterfbo)
6112                         {
6113                                 if (r_fb.water.depthtexture == NULL)
6114                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6115                                 if (p->fbo_reflection == 0)
6116                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6117                         }
6118                 }
6119         }
6120
6121         // render views
6122         r_refdef.view = originalview;
6123         r_refdef.view.showdebug = false;
6124         r_refdef.view.width = r_fb.water.waterwidth;
6125         r_refdef.view.height = r_fb.water.waterheight;
6126         r_refdef.view.useclipplane = true;
6127         myview = r_refdef.view;
6128         r_fb.water.renderingscene = true;
6129         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6130         {
6131                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6132                 {
6133                         r_refdef.view = myview;
6134                         if(r_water_scissormode.integer)
6135                         {
6136                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6137                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6138                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6139                         }
6140
6141                         // render reflected scene and copy into texture
6142                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6143                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6144                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6145                         r_refdef.view.clipplane = p->plane;
6146                         // reverse the cullface settings for this render
6147                         r_refdef.view.cullface_front = GL_FRONT;
6148                         r_refdef.view.cullface_back = GL_BACK;
6149                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6150                         {
6151                                 r_refdef.view.usecustompvs = true;
6152                                 if (p->pvsvalid)
6153                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6154                                 else
6155                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6156                         }
6157
6158                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6159                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6160                         R_ClearScreen(r_refdef.fogenabled);
6161                         if(r_water_scissormode.integer & 2)
6162                                 R_View_UpdateWithScissor(myscissor);
6163                         else
6164                                 R_View_Update();
6165                         R_AnimCache_CacheVisibleEntities();
6166                         if(r_water_scissormode.integer & 1)
6167                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6168                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6169
6170                         if (!p->fbo_reflection)
6171                                 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);
6172                         r_fb.water.hideplayer = false;
6173                 }
6174
6175                 // render the normal view scene and copy into texture
6176                 // (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)
6177                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6178                 {
6179                         r_refdef.view = myview;
6180                         if(r_water_scissormode.integer)
6181                         {
6182                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6183                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6184                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6185                         }
6186
6187                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6188
6189                         r_refdef.view.clipplane = p->plane;
6190                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6191                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6192
6193                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6194                         {
6195                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6196                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6197                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6198                                 R_RenderView_UpdateViewVectors();
6199                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6200                                 {
6201                                         r_refdef.view.usecustompvs = true;
6202                                         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);
6203                                 }
6204                         }
6205
6206                         PlaneClassify(&r_refdef.view.clipplane);
6207
6208                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6209                         R_ClearScreen(r_refdef.fogenabled);
6210                         if(r_water_scissormode.integer & 2)
6211                                 R_View_UpdateWithScissor(myscissor);
6212                         else
6213                                 R_View_Update();
6214                         R_AnimCache_CacheVisibleEntities();
6215                         if(r_water_scissormode.integer & 1)
6216                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6217                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6218
6219                         if (!p->fbo_refraction)
6220                                 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);
6221                         r_fb.water.hideplayer = false;
6222                 }
6223                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6224                 {
6225                         r_refdef.view = myview;
6226
6227                         r_refdef.view.clipplane = p->plane;
6228                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6229                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6230
6231                         r_refdef.view.width = r_fb.water.camerawidth;
6232                         r_refdef.view.height = r_fb.water.cameraheight;
6233                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6234                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6235                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6236                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6237
6238                         if(p->camera_entity)
6239                         {
6240                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6241                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6242                         }
6243
6244                         // note: all of the view is used for displaying... so
6245                         // there is no use in scissoring
6246
6247                         // reverse the cullface settings for this render
6248                         r_refdef.view.cullface_front = GL_FRONT;
6249                         r_refdef.view.cullface_back = GL_BACK;
6250                         // also reverse the view matrix
6251                         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
6252                         R_RenderView_UpdateViewVectors();
6253                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6254                         {
6255                                 r_refdef.view.usecustompvs = true;
6256                                 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);
6257                         }
6258                         
6259                         // camera needs no clipplane
6260                         r_refdef.view.useclipplane = false;
6261
6262                         PlaneClassify(&r_refdef.view.clipplane);
6263
6264                         r_fb.water.hideplayer = false;
6265
6266                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6267                         R_ClearScreen(r_refdef.fogenabled);
6268                         R_View_Update();
6269                         R_AnimCache_CacheVisibleEntities();
6270                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6271
6272                         if (!p->fbo_camera)
6273                                 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);
6274                         r_fb.water.hideplayer = false;
6275                 }
6276
6277         }
6278         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6279         r_fb.water.renderingscene = false;
6280         r_refdef.view = originalview;
6281         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6282         if (!r_fb.water.depthtexture)
6283                 R_ClearScreen(r_refdef.fogenabled);
6284         R_View_Update();
6285         R_AnimCache_CacheVisibleEntities();
6286         goto finish;
6287 error:
6288         r_refdef.view = originalview;
6289         r_fb.water.renderingscene = false;
6290         Cvar_SetValueQuick(&r_water, 0);
6291         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6292 finish:
6293         // lowquality hack, restore cvars
6294         if (qualityreduction > 0)
6295         {
6296                 if (qualityreduction >= 1)
6297                 {
6298                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6299                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6300                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6301                 }
6302                 if (qualityreduction >= 2)
6303                 {
6304                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6305                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6306                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6307                 }
6308         }
6309 }
6310
6311 static void R_Bloom_StartFrame(void)
6312 {
6313         int i;
6314         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6315         int viewwidth, viewheight;
6316         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6317         textype_t textype = TEXTYPE_COLORBUFFER;
6318
6319         switch (vid.renderpath)
6320         {
6321         case RENDERPATH_GL20:
6322                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6323                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6324                 {
6325                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6326                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6327                 }
6328                 break;
6329         case RENDERPATH_GL11:
6330         case RENDERPATH_GL13:
6331         case RENDERPATH_GLES1:
6332         case RENDERPATH_GLES2:
6333         case RENDERPATH_D3D9:
6334         case RENDERPATH_D3D10:
6335         case RENDERPATH_D3D11:
6336                 r_fb.usedepthtextures = false;
6337                 break;
6338         case RENDERPATH_SOFT:
6339                 r_fb.usedepthtextures = true;
6340                 break;
6341         }
6342
6343         if (r_viewscale_fpsscaling.integer)
6344         {
6345                 double actualframetime;
6346                 double targetframetime;
6347                 double adjust;
6348                 actualframetime = r_refdef.lastdrawscreentime;
6349                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6350                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6351                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6352                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6353                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6354                 viewscalefpsadjusted += adjust;
6355                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6356         }
6357         else
6358                 viewscalefpsadjusted = 1.0f;
6359
6360         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6361
6362         switch(vid.renderpath)
6363         {
6364         case RENDERPATH_GL20:
6365         case RENDERPATH_D3D9:
6366         case RENDERPATH_D3D10:
6367         case RENDERPATH_D3D11:
6368         case RENDERPATH_SOFT:
6369         case RENDERPATH_GLES2:
6370                 break;
6371         case RENDERPATH_GL11:
6372         case RENDERPATH_GL13:
6373         case RENDERPATH_GLES1:
6374                 return;
6375         }
6376
6377         // set bloomwidth and bloomheight to the bloom resolution that will be
6378         // used (often less than the screen resolution for faster rendering)
6379         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6380         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6381         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6382         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6383         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6384
6385         // calculate desired texture sizes
6386         if (vid.support.arb_texture_non_power_of_two)
6387         {
6388                 screentexturewidth = vid.width;
6389                 screentextureheight = vid.height;
6390                 bloomtexturewidth = r_fb.bloomwidth;
6391                 bloomtextureheight = r_fb.bloomheight;
6392         }
6393         else
6394         {
6395                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6396                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6397                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6398                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6399         }
6400
6401         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))
6402         {
6403                 Cvar_SetValueQuick(&r_bloom, 0);
6404                 Cvar_SetValueQuick(&r_motionblur, 0);
6405                 Cvar_SetValueQuick(&r_damageblur, 0);
6406         }
6407
6408         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6409          && !r_bloom.integer
6410          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6411          && !useviewfbo
6412          && r_viewscale.value == 1.0f
6413          && !r_viewscale_fpsscaling.integer)
6414                 screentexturewidth = screentextureheight = 0;
6415         if (!r_bloom.integer)
6416                 bloomtexturewidth = bloomtextureheight = 0;
6417
6418         // allocate textures as needed
6419         if (r_fb.screentexturewidth != screentexturewidth
6420          || r_fb.screentextureheight != screentextureheight
6421          || r_fb.bloomtexturewidth != bloomtexturewidth
6422          || r_fb.bloomtextureheight != bloomtextureheight
6423          || r_fb.textype != textype
6424          || useviewfbo != (r_fb.fbo != 0))
6425         {
6426                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6427                 {
6428                         if (r_fb.bloomtexture[i])
6429                                 R_FreeTexture(r_fb.bloomtexture[i]);
6430                         r_fb.bloomtexture[i] = NULL;
6431
6432                         if (r_fb.bloomfbo[i])
6433                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6434                         r_fb.bloomfbo[i] = 0;
6435                 }
6436
6437                 if (r_fb.fbo)
6438                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6439                 r_fb.fbo = 0;
6440
6441                 if (r_fb.colortexture)
6442                         R_FreeTexture(r_fb.colortexture);
6443                 r_fb.colortexture = NULL;
6444
6445                 if (r_fb.depthtexture)
6446                         R_FreeTexture(r_fb.depthtexture);
6447                 r_fb.depthtexture = NULL;
6448
6449                 if (r_fb.ghosttexture)
6450                         R_FreeTexture(r_fb.ghosttexture);
6451                 r_fb.ghosttexture = NULL;
6452
6453                 r_fb.screentexturewidth = screentexturewidth;
6454                 r_fb.screentextureheight = screentextureheight;
6455                 r_fb.bloomtexturewidth = bloomtexturewidth;
6456                 r_fb.bloomtextureheight = bloomtextureheight;
6457                 r_fb.textype = textype;
6458
6459                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6460                 {
6461                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6462                                 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);
6463                         r_fb.ghosttexture_valid = false;
6464                         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);
6465                         if (useviewfbo)
6466                         {
6467                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6468                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6469                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6470                         }
6471                 }
6472
6473                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6474                 {
6475                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6476                         {
6477                                 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);
6478                                 if (useviewfbo)
6479                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6480                         }
6481                 }
6482         }
6483
6484         // bloom texture is a different resolution
6485         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6486         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6487         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6488         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6489         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6490
6491         // set up a texcoord array for the full resolution screen image
6492         // (we have to keep this around to copy back during final render)
6493         r_fb.screentexcoord2f[0] = 0;
6494         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6495         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6496         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6497         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6498         r_fb.screentexcoord2f[5] = 0;
6499         r_fb.screentexcoord2f[6] = 0;
6500         r_fb.screentexcoord2f[7] = 0;
6501
6502         if(r_fb.fbo) 
6503         {
6504                 for (i = 1;i < 8;i += 2)
6505                 {
6506                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6507                 }
6508         }
6509
6510         // set up a texcoord array for the reduced resolution bloom image
6511         // (which will be additive blended over the screen image)
6512         r_fb.bloomtexcoord2f[0] = 0;
6513         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6514         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6515         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6516         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6517         r_fb.bloomtexcoord2f[5] = 0;
6518         r_fb.bloomtexcoord2f[6] = 0;
6519         r_fb.bloomtexcoord2f[7] = 0;
6520
6521         switch(vid.renderpath)
6522         {
6523         case RENDERPATH_GL11:
6524         case RENDERPATH_GL13:
6525         case RENDERPATH_GL20:
6526         case RENDERPATH_SOFT:
6527         case RENDERPATH_GLES1:
6528         case RENDERPATH_GLES2:
6529                 break;
6530         case RENDERPATH_D3D9:
6531         case RENDERPATH_D3D10:
6532         case RENDERPATH_D3D11:
6533                 for (i = 0;i < 4;i++)
6534                 {
6535                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6536                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6537                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6538                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6539                 }
6540                 break;
6541         }
6542
6543         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6544
6545         if (r_fb.fbo)
6546                 r_refdef.view.clear = true;
6547 }
6548
6549 static void R_Bloom_MakeTexture(void)
6550 {
6551         int x, range, dir;
6552         float xoffset, yoffset, r, brighten;
6553         rtexture_t *intex;
6554         float colorscale = r_bloom_colorscale.value;
6555
6556         r_refdef.stats[r_stat_bloom]++;
6557     
6558 #if 0
6559     // this copy is unnecessary since it happens in R_BlendView already
6560         if (!r_fb.fbo)
6561         {
6562                 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);
6563                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6564         }
6565 #endif
6566
6567         // scale down screen texture to the bloom texture size
6568         CHECKGLERROR
6569         r_fb.bloomindex = 0;
6570         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6571         R_SetViewport(&r_fb.bloomviewport);
6572         GL_DepthTest(false);
6573         GL_BlendFunc(GL_ONE, GL_ZERO);
6574         GL_Color(colorscale, colorscale, colorscale, 1);
6575         // 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...
6576         switch(vid.renderpath)
6577         {
6578         case RENDERPATH_GL11:
6579         case RENDERPATH_GL13:
6580         case RENDERPATH_GL20:
6581         case RENDERPATH_GLES1:
6582         case RENDERPATH_GLES2:
6583         case RENDERPATH_SOFT:
6584                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6585                 break;
6586         case RENDERPATH_D3D9:
6587         case RENDERPATH_D3D10:
6588         case RENDERPATH_D3D11:
6589                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6590                 break;
6591         }
6592         // TODO: do boxfilter scale-down in shader?
6593         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6594         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6595         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6596
6597         // we now have a properly scaled bloom image
6598         if (!r_fb.bloomfbo[r_fb.bloomindex])
6599         {
6600                 // copy it into the bloom texture
6601                 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);
6602                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6603         }
6604
6605         // multiply bloom image by itself as many times as desired
6606         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6607         {
6608                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6609                 r_fb.bloomindex ^= 1;
6610                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6611                 x *= 2;
6612                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6613                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6614                 {
6615                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6616                         GL_Color(r,r,r,1); // apply fix factor
6617                 }
6618                 else
6619                 {
6620                         if(x <= 2)
6621                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6622                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6623                         GL_Color(1,1,1,1); // no fix factor supported here
6624                 }
6625                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6626                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6627                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6628                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6629
6630                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6631                 {
6632                         // copy the darkened image to a texture
6633                         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);
6634                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6635                 }
6636         }
6637
6638         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6639         brighten = r_bloom_brighten.value;
6640         brighten = sqrt(brighten);
6641         if(range >= 1)
6642                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6643
6644         for (dir = 0;dir < 2;dir++)
6645         {
6646                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6647                 r_fb.bloomindex ^= 1;
6648                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6649                 // blend on at multiple vertical offsets to achieve a vertical blur
6650                 // TODO: do offset blends using GLSL
6651                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6652                 GL_BlendFunc(GL_ONE, GL_ZERO);
6653                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6654                 for (x = -range;x <= range;x++)
6655                 {
6656                         if (!dir){xoffset = 0;yoffset = x;}
6657                         else {xoffset = x;yoffset = 0;}
6658                         xoffset /= (float)r_fb.bloomtexturewidth;
6659                         yoffset /= (float)r_fb.bloomtextureheight;
6660                         // compute a texcoord array with the specified x and y offset
6661                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6662                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6663                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6664                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6665                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6666                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6667                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6668                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6669                         // this r value looks like a 'dot' particle, fading sharply to
6670                         // black at the edges
6671                         // (probably not realistic but looks good enough)
6672                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6673                         //r = brighten/(range*2+1);
6674                         r = brighten / (range * 2 + 1);
6675                         if(range >= 1)
6676                                 r *= (1 - x*x/(float)(range*range));
6677                         GL_Color(r, r, r, 1);
6678                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6679                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6680                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6681                         GL_BlendFunc(GL_ONE, GL_ONE);
6682                 }
6683
6684                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6685                 {
6686                         // copy the vertically or horizontally blurred bloom view to a texture
6687                         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);
6688                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6689                 }
6690         }
6691 }
6692
6693 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6694 {
6695         unsigned int permutation;
6696         float uservecs[4][4];
6697
6698         R_EntityMatrix(&identitymatrix);
6699
6700         switch (vid.renderpath)
6701         {
6702         case RENDERPATH_GL20:
6703         case RENDERPATH_D3D9:
6704         case RENDERPATH_D3D10:
6705         case RENDERPATH_D3D11:
6706         case RENDERPATH_SOFT:
6707         case RENDERPATH_GLES2:
6708                 permutation =
6709                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6710                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6711                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6712                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6713                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6714
6715                 if (r_fb.colortexture)
6716                 {
6717                         if (!r_fb.fbo)
6718                         {
6719                                 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);
6720                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6721                         }
6722
6723                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6724                         {
6725                                 // declare variables
6726                                 float blur_factor, blur_mouseaccel, blur_velocity;
6727                                 static float blur_average; 
6728                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6729
6730                                 // set a goal for the factoring
6731                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6732                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6733                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6734                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6735                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6736                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6737
6738                                 // from the goal, pick an averaged value between goal and last value
6739                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6740                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6741
6742                                 // enforce minimum amount of blur 
6743                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6744
6745                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6746
6747                                 // calculate values into a standard alpha
6748                                 cl.motionbluralpha = 1 - exp(-
6749                                                 (
6750                                                  (r_motionblur.value * blur_factor / 80)
6751                                                  +
6752                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6753                                                 )
6754                                                 /
6755                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6756                                           );
6757
6758                                 // randomization for the blur value to combat persistent ghosting
6759                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6760                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6761
6762                                 // apply the blur
6763                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6764                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6765                                 {
6766                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6767                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6768                                         switch(vid.renderpath)
6769                                         {
6770                                         case RENDERPATH_GL11:
6771                                         case RENDERPATH_GL13:
6772                                         case RENDERPATH_GL20:
6773                                         case RENDERPATH_GLES1:
6774                                         case RENDERPATH_GLES2:
6775                                         case RENDERPATH_SOFT:
6776                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6777                                                 break;
6778                                         case RENDERPATH_D3D9:
6779                                         case RENDERPATH_D3D10:
6780                                         case RENDERPATH_D3D11:
6781                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6782                                                 break;
6783                                         }
6784                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6785                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6786                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6787                                 }
6788
6789                                 // updates old view angles for next pass
6790                                 VectorCopy(cl.viewangles, blur_oldangles);
6791
6792                                 // copy view into the ghost texture
6793                                 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);
6794                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6795                                 r_fb.ghosttexture_valid = true;
6796                         }
6797                 }
6798                 else
6799                 {
6800                         // no r_fb.colortexture means we're rendering to the real fb
6801                         // we may still have to do view tint...
6802                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6803                         {
6804                                 // apply a color tint to the whole view
6805                                 R_ResetViewRendering2D(0, NULL, NULL);
6806                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6807                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6808                                 R_SetupShader_Generic_NoTexture(false, true);
6809                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6810                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6811                         }
6812                         break; // no screen processing, no bloom, skip it
6813                 }
6814
6815                 if (r_fb.bloomtexture[0])
6816                 {
6817                         // make the bloom texture
6818                         R_Bloom_MakeTexture();
6819                 }
6820
6821 #if _MSC_VER >= 1400
6822 #define sscanf sscanf_s
6823 #endif
6824                 memset(uservecs, 0, sizeof(uservecs));
6825                 if (r_glsl_postprocess_uservec1_enable.integer)
6826                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6827                 if (r_glsl_postprocess_uservec2_enable.integer)
6828                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6829                 if (r_glsl_postprocess_uservec3_enable.integer)
6830                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6831                 if (r_glsl_postprocess_uservec4_enable.integer)
6832                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6833
6834                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6835                 GL_Color(1, 1, 1, 1);
6836                 GL_BlendFunc(GL_ONE, GL_ZERO);
6837
6838                 switch(vid.renderpath)
6839                 {
6840                 case RENDERPATH_GL20:
6841                 case RENDERPATH_GLES2:
6842                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6843                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6844                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6845                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6846                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6847                         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]);
6848                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6849                         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]);
6850                         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]);
6851                         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]);
6852                         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]);
6853                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6854                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6855                         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);
6856                         break;
6857                 case RENDERPATH_D3D9:
6858 #ifdef SUPPORTD3D
6859                         // 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...
6860                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6861                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6862                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6863                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6864                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6865                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6866                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6867                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6868                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6869                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6870                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6871                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6872                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6873                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6874 #endif
6875                         break;
6876                 case RENDERPATH_D3D10:
6877                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6878                         break;
6879                 case RENDERPATH_D3D11:
6880                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6881                         break;
6882                 case RENDERPATH_SOFT:
6883                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6884                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6885                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6886                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6887                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6888                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6889                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6890                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6891                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6892                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6893                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6894                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6895                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6896                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6897                         break;
6898                 default:
6899                         break;
6900                 }
6901                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6902                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6903                 break;
6904         case RENDERPATH_GL11:
6905         case RENDERPATH_GL13:
6906         case RENDERPATH_GLES1:
6907                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6908                 {
6909                         // apply a color tint to the whole view
6910                         R_ResetViewRendering2D(0, NULL, NULL);
6911                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6912                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6913                         R_SetupShader_Generic_NoTexture(false, true);
6914                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6915                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6916                 }
6917                 break;
6918         }
6919 }
6920
6921 matrix4x4_t r_waterscrollmatrix;
6922
6923 void R_UpdateFog(void)
6924 {
6925         // Nehahra fog
6926         if (gamemode == GAME_NEHAHRA)
6927         {
6928                 if (gl_fogenable.integer)
6929                 {
6930                         r_refdef.oldgl_fogenable = true;
6931                         r_refdef.fog_density = gl_fogdensity.value;
6932                         r_refdef.fog_red = gl_fogred.value;
6933                         r_refdef.fog_green = gl_foggreen.value;
6934                         r_refdef.fog_blue = gl_fogblue.value;
6935                         r_refdef.fog_alpha = 1;
6936                         r_refdef.fog_start = 0;
6937                         r_refdef.fog_end = gl_skyclip.value;
6938                         r_refdef.fog_height = 1<<30;
6939                         r_refdef.fog_fadedepth = 128;
6940                 }
6941                 else if (r_refdef.oldgl_fogenable)
6942                 {
6943                         r_refdef.oldgl_fogenable = false;
6944                         r_refdef.fog_density = 0;
6945                         r_refdef.fog_red = 0;
6946                         r_refdef.fog_green = 0;
6947                         r_refdef.fog_blue = 0;
6948                         r_refdef.fog_alpha = 0;
6949                         r_refdef.fog_start = 0;
6950                         r_refdef.fog_end = 0;
6951                         r_refdef.fog_height = 1<<30;
6952                         r_refdef.fog_fadedepth = 128;
6953                 }
6954         }
6955
6956         // fog parms
6957         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6958         r_refdef.fog_start = max(0, r_refdef.fog_start);
6959         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6960
6961         if (r_refdef.fog_density && r_drawfog.integer)
6962         {
6963                 r_refdef.fogenabled = true;
6964                 // this is the point where the fog reaches 0.9986 alpha, which we
6965                 // consider a good enough cutoff point for the texture
6966                 // (0.9986 * 256 == 255.6)
6967                 if (r_fog_exp2.integer)
6968                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6969                 else
6970                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6971                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6972                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6973                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6974                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6975                         R_BuildFogHeightTexture();
6976                 // fog color was already set
6977                 // update the fog texture
6978                 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)
6979                         R_BuildFogTexture();
6980                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6981                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6982         }
6983         else
6984                 r_refdef.fogenabled = false;
6985
6986         // fog color
6987         if (r_refdef.fog_density)
6988         {
6989                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6990                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6991                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6992
6993                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6994                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6995                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6996                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6997
6998                 {
6999                         vec3_t fogvec;
7000                         VectorCopy(r_refdef.fogcolor, fogvec);
7001                         //   color.rgb *= ContrastBoost * SceneBrightness;
7002                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7003                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7004                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7005                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7006                 }
7007         }
7008 }
7009
7010 void R_UpdateVariables(void)
7011 {
7012         R_Textures_Frame();
7013
7014         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7015
7016         r_refdef.farclip = r_farclip_base.value;
7017         if (r_refdef.scene.worldmodel)
7018                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7019         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7020
7021         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7022                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7023         r_refdef.polygonfactor = 0;
7024         r_refdef.polygonoffset = 0;
7025         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7026         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7027
7028         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7029         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7030         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7031         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7032         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7033         if (FAKELIGHT_ENABLED)
7034         {
7035                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7036         }
7037         else if (r_refdef.scene.worldmodel)
7038         {
7039                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7040         }
7041         if (r_showsurfaces.integer)
7042         {
7043                 r_refdef.scene.rtworld = false;
7044                 r_refdef.scene.rtworldshadows = false;
7045                 r_refdef.scene.rtdlight = false;
7046                 r_refdef.scene.rtdlightshadows = false;
7047                 r_refdef.lightmapintensity = 0;
7048         }
7049
7050         r_gpuskeletal = false;
7051         switch(vid.renderpath)
7052         {
7053         case RENDERPATH_GL20:
7054                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7055         case RENDERPATH_D3D9:
7056         case RENDERPATH_D3D10:
7057         case RENDERPATH_D3D11:
7058         case RENDERPATH_SOFT:
7059         case RENDERPATH_GLES2:
7060                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7061                 {
7062                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7063                         {
7064                                 // build GLSL gamma texture
7065 #define RAMPWIDTH 256
7066                                 unsigned short ramp[RAMPWIDTH * 3];
7067                                 unsigned char rampbgr[RAMPWIDTH][4];
7068                                 int i;
7069
7070                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7071
7072                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7073                                 for(i = 0; i < RAMPWIDTH; ++i)
7074                                 {
7075                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7076                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7077                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7078                                         rampbgr[i][3] = 0;
7079                                 }
7080                                 if (r_texture_gammaramps)
7081                                 {
7082                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7083                                 }
7084                                 else
7085                                 {
7086                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7087                                 }
7088                         }
7089                 }
7090                 else
7091                 {
7092                         // remove GLSL gamma texture
7093                 }
7094                 break;
7095         case RENDERPATH_GL11:
7096         case RENDERPATH_GL13:
7097         case RENDERPATH_GLES1:
7098                 break;
7099         }
7100 }
7101
7102 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7103 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7104 /*
7105 ================
7106 R_SelectScene
7107 ================
7108 */
7109 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7110         if( scenetype != r_currentscenetype ) {
7111                 // store the old scenetype
7112                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7113                 r_currentscenetype = scenetype;
7114                 // move in the new scene
7115                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7116         }
7117 }
7118
7119 /*
7120 ================
7121 R_GetScenePointer
7122 ================
7123 */
7124 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7125 {
7126         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7127         if( scenetype == r_currentscenetype ) {
7128                 return &r_refdef.scene;
7129         } else {
7130                 return &r_scenes_store[ scenetype ];
7131         }
7132 }
7133
7134 static int R_SortEntities_Compare(const void *ap, const void *bp)
7135 {
7136         const entity_render_t *a = *(const entity_render_t **)ap;
7137         const entity_render_t *b = *(const entity_render_t **)bp;
7138
7139         // 1. compare model
7140         if(a->model < b->model)
7141                 return -1;
7142         if(a->model > b->model)
7143                 return +1;
7144
7145         // 2. compare skin
7146         // TODO possibly calculate the REAL skinnum here first using
7147         // skinscenes?
7148         if(a->skinnum < b->skinnum)
7149                 return -1;
7150         if(a->skinnum > b->skinnum)
7151                 return +1;
7152
7153         // everything we compared is equal
7154         return 0;
7155 }
7156 static void R_SortEntities(void)
7157 {
7158         // below or equal 2 ents, sorting never gains anything
7159         if(r_refdef.scene.numentities <= 2)
7160                 return;
7161         // sort
7162         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7163 }
7164
7165 /*
7166 ================
7167 R_RenderView
7168 ================
7169 */
7170 int dpsoftrast_test;
7171 extern cvar_t r_shadow_bouncegrid;
7172 void R_RenderView(void)
7173 {
7174         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7175         int fbo;
7176         rtexture_t *depthtexture;
7177         rtexture_t *colortexture;
7178
7179         dpsoftrast_test = r_test.integer;
7180
7181         if (r_timereport_active)
7182                 R_TimeReport("start");
7183         r_textureframe++; // used only by R_GetCurrentTexture
7184         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7185
7186         if(R_CompileShader_CheckStaticParms())
7187                 R_GLSL_Restart_f();
7188
7189         if (!r_drawentities.integer)
7190                 r_refdef.scene.numentities = 0;
7191         else if (r_sortentities.integer)
7192                 R_SortEntities();
7193
7194         R_AnimCache_ClearCache();
7195         R_FrameData_NewFrame();
7196         R_BufferData_NewFrame();
7197
7198         /* adjust for stereo display */
7199         if(R_Stereo_Active())
7200         {
7201                 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);
7202                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7203         }
7204
7205         if (r_refdef.view.isoverlay)
7206         {
7207                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7208                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7209                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7210                 R_TimeReport("depthclear");
7211
7212                 r_refdef.view.showdebug = false;
7213
7214                 r_fb.water.enabled = false;
7215                 r_fb.water.numwaterplanes = 0;
7216
7217                 R_RenderScene(0, NULL, NULL);
7218
7219                 r_refdef.view.matrix = originalmatrix;
7220
7221                 CHECKGLERROR
7222                 return;
7223         }
7224
7225         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7226         {
7227                 r_refdef.view.matrix = originalmatrix;
7228                 return;
7229         }
7230
7231         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7232
7233         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7234                 // in sRGB fallback, behave similar to true sRGB: convert this
7235                 // value from linear to sRGB
7236                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7237
7238         R_RenderView_UpdateViewVectors();
7239
7240         R_Shadow_UpdateWorldLightSelection();
7241
7242         R_Bloom_StartFrame();
7243
7244         // apply bloom brightness offset
7245         if(r_fb.bloomtexture[0])
7246                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7247
7248         R_Water_StartFrame();
7249
7250         // now we probably have an fbo to render into
7251         fbo = r_fb.fbo;
7252         depthtexture = r_fb.depthtexture;
7253         colortexture = r_fb.colortexture;
7254
7255         CHECKGLERROR
7256         if (r_timereport_active)
7257                 R_TimeReport("viewsetup");
7258
7259         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7260
7261         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7262         {
7263                 R_ClearScreen(r_refdef.fogenabled);
7264                 if (r_timereport_active)
7265                         R_TimeReport("viewclear");
7266         }
7267         r_refdef.view.clear = true;
7268
7269         r_refdef.view.showdebug = true;
7270
7271         R_View_Update();
7272         if (r_timereport_active)
7273                 R_TimeReport("visibility");
7274
7275         R_AnimCache_CacheVisibleEntities();
7276         if (r_timereport_active)
7277                 R_TimeReport("animcache");
7278
7279         R_Shadow_UpdateBounceGridTexture();
7280         if (r_timereport_active && r_shadow_bouncegrid.integer)
7281                 R_TimeReport("bouncegrid");
7282
7283         r_fb.water.numwaterplanes = 0;
7284         if (r_fb.water.enabled)
7285                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7286
7287         R_RenderScene(fbo, depthtexture, colortexture);
7288         r_fb.water.numwaterplanes = 0;
7289
7290         R_BlendView(fbo, depthtexture, colortexture);
7291         if (r_timereport_active)
7292                 R_TimeReport("blendview");
7293
7294         GL_Scissor(0, 0, vid.width, vid.height);
7295         GL_ScissorTest(false);
7296
7297         r_refdef.view.matrix = originalmatrix;
7298
7299         CHECKGLERROR
7300 }
7301
7302 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7303 {
7304         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7305         {
7306                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7307                 if (r_timereport_active)
7308                         R_TimeReport("waterworld");
7309         }
7310
7311         // don't let sound skip if going slow
7312         if (r_refdef.scene.extraupdate)
7313                 S_ExtraUpdate ();
7314
7315         R_DrawModelsAddWaterPlanes();
7316         if (r_timereport_active)
7317                 R_TimeReport("watermodels");
7318
7319         if (r_fb.water.numwaterplanes)
7320         {
7321                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7322                 if (r_timereport_active)
7323                         R_TimeReport("waterscenes");
7324         }
7325 }
7326
7327 extern cvar_t cl_locs_show;
7328 static void R_DrawLocs(void);
7329 static void R_DrawEntityBBoxes(void);
7330 static void R_DrawModelDecals(void);
7331 extern cvar_t cl_decals_newsystem;
7332 extern qboolean r_shadow_usingdeferredprepass;
7333 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7334 {
7335         qboolean shadowmapping = false;
7336
7337         if (r_timereport_active)
7338                 R_TimeReport("beginscene");
7339
7340         r_refdef.stats[r_stat_renders]++;
7341
7342         R_UpdateFog();
7343
7344         // don't let sound skip if going slow
7345         if (r_refdef.scene.extraupdate)
7346                 S_ExtraUpdate ();
7347
7348         R_MeshQueue_BeginScene();
7349
7350         R_SkyStartFrame();
7351
7352         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);
7353
7354         if (r_timereport_active)
7355                 R_TimeReport("skystartframe");
7356
7357         if (cl.csqc_vidvars.drawworld)
7358         {
7359                 // don't let sound skip if going slow
7360                 if (r_refdef.scene.extraupdate)
7361                         S_ExtraUpdate ();
7362
7363                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7364                 {
7365                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7366                         if (r_timereport_active)
7367                                 R_TimeReport("worldsky");
7368                 }
7369
7370                 if (R_DrawBrushModelsSky() && r_timereport_active)
7371                         R_TimeReport("bmodelsky");
7372
7373                 if (skyrendermasked && skyrenderlater)
7374                 {
7375                         // we have to force off the water clipping plane while rendering sky
7376                         R_SetupView(false, fbo, depthtexture, colortexture);
7377                         R_Sky();
7378                         R_SetupView(true, fbo, depthtexture, colortexture);
7379                         if (r_timereport_active)
7380                                 R_TimeReport("sky");
7381                 }
7382         }
7383
7384         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7385         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7386                 R_Shadow_PrepareModelShadows();
7387         if (r_timereport_active)
7388                 R_TimeReport("preparelights");
7389
7390         if (R_Shadow_ShadowMappingEnabled())
7391                 shadowmapping = true;
7392
7393         if (r_shadow_usingdeferredprepass)
7394                 R_Shadow_DrawPrepass();
7395
7396         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7397         {
7398                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7399                 if (r_timereport_active)
7400                         R_TimeReport("worlddepth");
7401         }
7402         if (r_depthfirst.integer >= 2)
7403         {
7404                 R_DrawModelsDepth();
7405                 if (r_timereport_active)
7406                         R_TimeReport("modeldepth");
7407         }
7408
7409         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7410         {
7411                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7412                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7413                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7414                 // don't let sound skip if going slow
7415                 if (r_refdef.scene.extraupdate)
7416                         S_ExtraUpdate ();
7417         }
7418
7419         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7420         {
7421                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7422                 if (r_timereport_active)
7423                         R_TimeReport("world");
7424         }
7425
7426         // don't let sound skip if going slow
7427         if (r_refdef.scene.extraupdate)
7428                 S_ExtraUpdate ();
7429
7430         R_DrawModels();
7431         if (r_timereport_active)
7432                 R_TimeReport("models");
7433
7434         // don't let sound skip if going slow
7435         if (r_refdef.scene.extraupdate)
7436                 S_ExtraUpdate ();
7437
7438         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7439         {
7440                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7441                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7442                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7443                 // don't let sound skip if going slow
7444                 if (r_refdef.scene.extraupdate)
7445                         S_ExtraUpdate ();
7446         }
7447
7448         if (!r_shadow_usingdeferredprepass)
7449         {
7450                 R_Shadow_DrawLights();
7451                 if (r_timereport_active)
7452                         R_TimeReport("rtlights");
7453         }
7454
7455         // don't let sound skip if going slow
7456         if (r_refdef.scene.extraupdate)
7457                 S_ExtraUpdate ();
7458
7459         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7460         {
7461                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7462                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7463                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7464                 // don't let sound skip if going slow
7465                 if (r_refdef.scene.extraupdate)
7466                         S_ExtraUpdate ();
7467         }
7468
7469         if (cl.csqc_vidvars.drawworld)
7470         {
7471                 if (cl_decals_newsystem.integer)
7472                 {
7473                         R_DrawModelDecals();
7474                         if (r_timereport_active)
7475                                 R_TimeReport("modeldecals");
7476                 }
7477                 else
7478                 {
7479                         R_DrawDecals();
7480                         if (r_timereport_active)
7481                                 R_TimeReport("decals");
7482                 }
7483
7484                 R_DrawParticles();
7485                 if (r_timereport_active)
7486                         R_TimeReport("particles");
7487
7488                 R_DrawExplosions();
7489                 if (r_timereport_active)
7490                         R_TimeReport("explosions");
7491
7492                 R_DrawLightningBeams();
7493                 if (r_timereport_active)
7494                         R_TimeReport("lightning");
7495         }
7496
7497         if (cl.csqc_loaded)
7498                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7499
7500         if (r_refdef.view.showdebug)
7501         {
7502                 if (cl_locs_show.integer)
7503                 {
7504                         R_DrawLocs();
7505                         if (r_timereport_active)
7506                                 R_TimeReport("showlocs");
7507                 }
7508
7509                 if (r_drawportals.integer)
7510                 {
7511                         R_DrawPortals();
7512                         if (r_timereport_active)
7513                                 R_TimeReport("portals");
7514                 }
7515
7516                 if (r_showbboxes.value > 0)
7517                 {
7518                         R_DrawEntityBBoxes();
7519                         if (r_timereport_active)
7520                                 R_TimeReport("bboxes");
7521                 }
7522         }
7523
7524         if (r_transparent.integer)
7525         {
7526                 R_MeshQueue_RenderTransparent();
7527                 if (r_timereport_active)
7528                         R_TimeReport("drawtrans");
7529         }
7530
7531         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))
7532         {
7533                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7534                 if (r_timereport_active)
7535                         R_TimeReport("worlddebug");
7536                 R_DrawModelsDebug();
7537                 if (r_timereport_active)
7538                         R_TimeReport("modeldebug");
7539         }
7540
7541         if (cl.csqc_vidvars.drawworld)
7542         {
7543                 R_Shadow_DrawCoronas();
7544                 if (r_timereport_active)
7545                         R_TimeReport("coronas");
7546         }
7547
7548 #if 0
7549         {
7550                 GL_DepthTest(false);
7551                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7552                 GL_Color(1, 1, 1, 1);
7553                 qglBegin(GL_POLYGON);
7554                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7555                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7556                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7557                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7558                 qglEnd();
7559                 qglBegin(GL_POLYGON);
7560                 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]);
7561                 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]);
7562                 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]);
7563                 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]);
7564                 qglEnd();
7565                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7566         }
7567 #endif
7568
7569         // don't let sound skip if going slow
7570         if (r_refdef.scene.extraupdate)
7571                 S_ExtraUpdate ();
7572 }
7573
7574 static const unsigned short bboxelements[36] =
7575 {
7576         5, 1, 3, 5, 3, 7,
7577         6, 2, 0, 6, 0, 4,
7578         7, 3, 2, 7, 2, 6,
7579         4, 0, 1, 4, 1, 5,
7580         4, 5, 7, 4, 7, 6,
7581         1, 0, 2, 1, 2, 3,
7582 };
7583
7584 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7585 {
7586         int i;
7587         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7588
7589         RSurf_ActiveWorldEntity();
7590
7591         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7592         GL_DepthMask(false);
7593         GL_DepthRange(0, 1);
7594         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7595 //      R_Mesh_ResetTextureState();
7596
7597         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7598         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7599         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7600         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7601         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7602         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7603         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7604         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7605         R_FillColors(color4f, 8, cr, cg, cb, ca);
7606         if (r_refdef.fogenabled)
7607         {
7608                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7609                 {
7610                         f1 = RSurf_FogVertex(v);
7611                         f2 = 1 - f1;
7612                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7613                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7614                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7615                 }
7616         }
7617         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7618         R_Mesh_ResetTextureState();
7619         R_SetupShader_Generic_NoTexture(false, false);
7620         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7621 }
7622
7623 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7624 {
7625         prvm_prog_t *prog = SVVM_prog;
7626         int i;
7627         float color[4];
7628         prvm_edict_t *edict;
7629
7630         // this function draws bounding boxes of server entities
7631         if (!sv.active)
7632                 return;
7633
7634         GL_CullFace(GL_NONE);
7635         R_SetupShader_Generic_NoTexture(false, false);
7636
7637         for (i = 0;i < numsurfaces;i++)
7638         {
7639                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7640                 switch ((int)PRVM_serveredictfloat(edict, solid))
7641                 {
7642                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7643                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7644                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7645                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7646                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7647                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7648                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7649                 }
7650                 color[3] *= r_showbboxes.value;
7651                 color[3] = bound(0, color[3], 1);
7652                 GL_DepthTest(!r_showdisabledepthtest.integer);
7653                 GL_CullFace(r_refdef.view.cullface_front);
7654                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7655         }
7656 }
7657
7658 static void R_DrawEntityBBoxes(void)
7659 {
7660         int i;
7661         prvm_edict_t *edict;
7662         vec3_t center;
7663         prvm_prog_t *prog = SVVM_prog;
7664
7665         // this function draws bounding boxes of server entities
7666         if (!sv.active)
7667                 return;
7668
7669         for (i = 0;i < prog->num_edicts;i++)
7670         {
7671                 edict = PRVM_EDICT_NUM(i);
7672                 if (edict->priv.server->free)
7673                         continue;
7674                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7675                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7676                         continue;
7677                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7678                         continue;
7679                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7680                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7681         }
7682 }
7683
7684 static const int nomodelelement3i[24] =
7685 {
7686         5, 2, 0,
7687         5, 1, 2,
7688         5, 0, 3,
7689         5, 3, 1,
7690         0, 2, 4,
7691         2, 1, 4,
7692         3, 0, 4,
7693         1, 3, 4
7694 };
7695
7696 static const unsigned short nomodelelement3s[24] =
7697 {
7698         5, 2, 0,
7699         5, 1, 2,
7700         5, 0, 3,
7701         5, 3, 1,
7702         0, 2, 4,
7703         2, 1, 4,
7704         3, 0, 4,
7705         1, 3, 4
7706 };
7707
7708 static const float nomodelvertex3f[6*3] =
7709 {
7710         -16,   0,   0,
7711          16,   0,   0,
7712           0, -16,   0,
7713           0,  16,   0,
7714           0,   0, -16,
7715           0,   0,  16
7716 };
7717
7718 static const float nomodelcolor4f[6*4] =
7719 {
7720         0.0f, 0.0f, 0.5f, 1.0f,
7721         0.0f, 0.0f, 0.5f, 1.0f,
7722         0.0f, 0.5f, 0.0f, 1.0f,
7723         0.0f, 0.5f, 0.0f, 1.0f,
7724         0.5f, 0.0f, 0.0f, 1.0f,
7725         0.5f, 0.0f, 0.0f, 1.0f
7726 };
7727
7728 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7729 {
7730         int i;
7731         float f1, f2, *c;
7732         float color4f[6*4];
7733
7734         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);
7735
7736         // this is only called once per entity so numsurfaces is always 1, and
7737         // surfacelist is always {0}, so this code does not handle batches
7738
7739         if (rsurface.ent_flags & RENDER_ADDITIVE)
7740         {
7741                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7742                 GL_DepthMask(false);
7743         }
7744         else if (rsurface.colormod[3] < 1)
7745         {
7746                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7747                 GL_DepthMask(false);
7748         }
7749         else
7750         {
7751                 GL_BlendFunc(GL_ONE, GL_ZERO);
7752                 GL_DepthMask(true);
7753         }
7754         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7755         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7756         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7757         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7758         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7759         for (i = 0, c = color4f;i < 6;i++, c += 4)
7760         {
7761                 c[0] *= rsurface.colormod[0];
7762                 c[1] *= rsurface.colormod[1];
7763                 c[2] *= rsurface.colormod[2];
7764                 c[3] *= rsurface.colormod[3];
7765         }
7766         if (r_refdef.fogenabled)
7767         {
7768                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7769                 {
7770                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7771                         f2 = 1 - f1;
7772                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7773                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7774                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7775                 }
7776         }
7777 //      R_Mesh_ResetTextureState();
7778         R_SetupShader_Generic_NoTexture(false, false);
7779         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7780         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7781 }
7782
7783 void R_DrawNoModel(entity_render_t *ent)
7784 {
7785         vec3_t org;
7786         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7787         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7788                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7789         else
7790                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7791 }
7792
7793 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7794 {
7795         vec3_t right1, right2, diff, normal;
7796
7797         VectorSubtract (org2, org1, normal);
7798
7799         // calculate 'right' vector for start
7800         VectorSubtract (r_refdef.view.origin, org1, diff);
7801         CrossProduct (normal, diff, right1);
7802         VectorNormalize (right1);
7803
7804         // calculate 'right' vector for end
7805         VectorSubtract (r_refdef.view.origin, org2, diff);
7806         CrossProduct (normal, diff, right2);
7807         VectorNormalize (right2);
7808
7809         vert[ 0] = org1[0] + width * right1[0];
7810         vert[ 1] = org1[1] + width * right1[1];
7811         vert[ 2] = org1[2] + width * right1[2];
7812         vert[ 3] = org1[0] - width * right1[0];
7813         vert[ 4] = org1[1] - width * right1[1];
7814         vert[ 5] = org1[2] - width * right1[2];
7815         vert[ 6] = org2[0] - width * right2[0];
7816         vert[ 7] = org2[1] - width * right2[1];
7817         vert[ 8] = org2[2] - width * right2[2];
7818         vert[ 9] = org2[0] + width * right2[0];
7819         vert[10] = org2[1] + width * right2[1];
7820         vert[11] = org2[2] + width * right2[2];
7821 }
7822
7823 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)
7824 {
7825         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7826         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7827         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7828         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7829         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7830         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7831         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7832         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7833         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7834         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7835         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7836         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7837 }
7838
7839 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7840 {
7841         int i;
7842         float *vertex3f;
7843         float v[3];
7844         VectorSet(v, x, y, z);
7845         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7846                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7847                         break;
7848         if (i == mesh->numvertices)
7849         {
7850                 if (mesh->numvertices < mesh->maxvertices)
7851                 {
7852                         VectorCopy(v, vertex3f);
7853                         mesh->numvertices++;
7854                 }
7855                 return mesh->numvertices;
7856         }
7857         else
7858                 return i;
7859 }
7860
7861 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7862 {
7863         int i;
7864         int *e, element[3];
7865         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7866         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7867         e = mesh->element3i + mesh->numtriangles * 3;
7868         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7869         {
7870                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7871                 if (mesh->numtriangles < mesh->maxtriangles)
7872                 {
7873                         *e++ = element[0];
7874                         *e++ = element[1];
7875                         *e++ = element[2];
7876                         mesh->numtriangles++;
7877                 }
7878                 element[1] = element[2];
7879         }
7880 }
7881
7882 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7883 {
7884         int i;
7885         int *e, element[3];
7886         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7887         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7888         e = mesh->element3i + mesh->numtriangles * 3;
7889         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7890         {
7891                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7892                 if (mesh->numtriangles < mesh->maxtriangles)
7893                 {
7894                         *e++ = element[0];
7895                         *e++ = element[1];
7896                         *e++ = element[2];
7897                         mesh->numtriangles++;
7898                 }
7899                 element[1] = element[2];
7900         }
7901 }
7902
7903 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7904 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7905 {
7906         int planenum, planenum2;
7907         int w;
7908         int tempnumpoints;
7909         mplane_t *plane, *plane2;
7910         double maxdist;
7911         double temppoints[2][256*3];
7912         // figure out how large a bounding box we need to properly compute this brush
7913         maxdist = 0;
7914         for (w = 0;w < numplanes;w++)
7915                 maxdist = max(maxdist, fabs(planes[w].dist));
7916         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7917         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7918         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7919         {
7920                 w = 0;
7921                 tempnumpoints = 4;
7922                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7923                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7924                 {
7925                         if (planenum2 == planenum)
7926                                 continue;
7927                         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);
7928                         w = !w;
7929                 }
7930                 if (tempnumpoints < 3)
7931                         continue;
7932                 // generate elements forming a triangle fan for this polygon
7933                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7934         }
7935 }
7936
7937 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)
7938 {
7939         texturelayer_t *layer;
7940         layer = t->currentlayers + t->currentnumlayers++;
7941         layer->type = type;
7942         layer->depthmask = depthmask;
7943         layer->blendfunc1 = blendfunc1;
7944         layer->blendfunc2 = blendfunc2;
7945         layer->texture = texture;
7946         layer->texmatrix = *matrix;
7947         layer->color[0] = r;
7948         layer->color[1] = g;
7949         layer->color[2] = b;
7950         layer->color[3] = a;
7951 }
7952
7953 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7954 {
7955         if(parms[0] == 0 && parms[1] == 0)
7956                 return false;
7957         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7958                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7959                         return false;
7960         return true;
7961 }
7962
7963 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7964 {
7965         double index, f;
7966         index = parms[2] + rsurface.shadertime * parms[3];
7967         index -= floor(index);
7968         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7969         {
7970         default:
7971         case Q3WAVEFUNC_NONE:
7972         case Q3WAVEFUNC_NOISE:
7973         case Q3WAVEFUNC_COUNT:
7974                 f = 0;
7975                 break;
7976         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7977         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7978         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7979         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7980         case Q3WAVEFUNC_TRIANGLE:
7981                 index *= 4;
7982                 f = index - floor(index);
7983                 if (index < 1)
7984                 {
7985                         // f = f;
7986                 }
7987                 else if (index < 2)
7988                         f = 1 - f;
7989                 else if (index < 3)
7990                         f = -f;
7991                 else
7992                         f = -(1 - f);
7993                 break;
7994         }
7995         f = parms[0] + parms[1] * f;
7996         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7997                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7998         return (float) f;
7999 }
8000
8001 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8002 {
8003         int w, h, idx;
8004         double f;
8005         double offsetd[2];
8006         float tcmat[12];
8007         matrix4x4_t matrix, temp;
8008         switch(tcmod->tcmod)
8009         {
8010                 case Q3TCMOD_COUNT:
8011                 case Q3TCMOD_NONE:
8012                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8013                                 matrix = r_waterscrollmatrix;
8014                         else
8015                                 matrix = identitymatrix;
8016                         break;
8017                 case Q3TCMOD_ENTITYTRANSLATE:
8018                         // this is used in Q3 to allow the gamecode to control texcoord
8019                         // scrolling on the entity, which is not supported in darkplaces yet.
8020                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8021                         break;
8022                 case Q3TCMOD_ROTATE:
8023                         f = tcmod->parms[0] * rsurface.shadertime;
8024                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8025                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
8026                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8027                         break;
8028                 case Q3TCMOD_SCALE:
8029                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8030                         break;
8031                 case Q3TCMOD_SCROLL:
8032                         // extra care is needed because of precision breakdown with large values of time
8033                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8034                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8035                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8036                         break;
8037                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8038                         w = (int) tcmod->parms[0];
8039                         h = (int) tcmod->parms[1];
8040                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8041                         f = f - floor(f);
8042                         idx = (int) floor(f * w * h);
8043                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8044                         break;
8045                 case Q3TCMOD_STRETCH:
8046                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8047                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8048                         break;
8049                 case Q3TCMOD_TRANSFORM:
8050                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8051                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8052                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8053                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8054                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8055                         break;
8056                 case Q3TCMOD_TURBULENT:
8057                         // this is handled in the RSurf_PrepareVertices function
8058                         matrix = identitymatrix;
8059                         break;
8060         }
8061         temp = *texmatrix;
8062         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8063 }
8064
8065 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8066 {
8067         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8068         char name[MAX_QPATH];
8069         skinframe_t *skinframe;
8070         unsigned char pixels[296*194];
8071         strlcpy(cache->name, skinname, sizeof(cache->name));
8072         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8073         if (developer_loading.integer)
8074                 Con_Printf("loading %s\n", name);
8075         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8076         if (!skinframe || !skinframe->base)
8077         {
8078                 unsigned char *f;
8079                 fs_offset_t filesize;
8080                 skinframe = NULL;
8081                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8082                 if (f)
8083                 {
8084                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8085                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8086                         Mem_Free(f);
8087                 }
8088         }
8089         cache->skinframe = skinframe;
8090 }
8091
8092 texture_t *R_GetCurrentTexture(texture_t *t)
8093 {
8094         int i;
8095         const entity_render_t *ent = rsurface.entity;
8096         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8097         q3shaderinfo_layer_tcmod_t *tcmod;
8098
8099         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8100                 return t->currentframe;
8101         t->update_lastrenderframe = r_textureframe;
8102         t->update_lastrenderentity = (void *)ent;
8103
8104         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8105                 t->camera_entity = ent->entitynumber;
8106         else
8107                 t->camera_entity = 0;
8108
8109         // switch to an alternate material if this is a q1bsp animated material
8110         {
8111                 texture_t *texture = t;
8112                 int s = rsurface.ent_skinnum;
8113                 if ((unsigned int)s >= (unsigned int)model->numskins)
8114                         s = 0;
8115                 if (model->skinscenes)
8116                 {
8117                         if (model->skinscenes[s].framecount > 1)
8118                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8119                         else
8120                                 s = model->skinscenes[s].firstframe;
8121                 }
8122                 if (s > 0)
8123                         t = t + s * model->num_surfaces;
8124                 if (t->animated)
8125                 {
8126                         // use an alternate animation if the entity's frame is not 0,
8127                         // and only if the texture has an alternate animation
8128                         if (rsurface.ent_alttextures && t->anim_total[1])
8129                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8130                         else
8131                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8132                 }
8133                 texture->currentframe = t;
8134         }
8135
8136         // update currentskinframe to be a qw skin or animation frame
8137         if (rsurface.ent_qwskin >= 0)
8138         {
8139                 i = rsurface.ent_qwskin;
8140                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8141                 {
8142                         r_qwskincache_size = cl.maxclients;
8143                         if (r_qwskincache)
8144                                 Mem_Free(r_qwskincache);
8145                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8146                 }
8147                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8148                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8149                 t->currentskinframe = r_qwskincache[i].skinframe;
8150                 if (t->currentskinframe == NULL)
8151                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8152         }
8153         else if (t->numskinframes >= 2)
8154                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8155         if (t->backgroundnumskinframes >= 2)
8156                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8157
8158         t->currentmaterialflags = t->basematerialflags;
8159         t->currentalpha = rsurface.colormod[3];
8160         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8161                 t->currentalpha *= r_wateralpha.value;
8162         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8163                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8164         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8165                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8166         if (!(rsurface.ent_flags & RENDER_LIGHT))
8167                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8168         else if (FAKELIGHT_ENABLED)
8169         {
8170                 // no modellight if using fakelight for the map
8171         }
8172         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8173         {
8174                 // pick a model lighting mode
8175                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8176                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8177                 else
8178                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8179         }
8180         if (rsurface.ent_flags & RENDER_ADDITIVE)
8181                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8182         else if (t->currentalpha < 1)
8183                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8184         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8185         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8186                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8187         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8188                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8189         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8190                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8191         if (t->backgroundnumskinframes)
8192                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8193         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8194         {
8195                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8196                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8197         }
8198         else
8199                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8200         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8201         {
8202                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8203                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8204         }
8205         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8206                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8207
8208         // there is no tcmod
8209         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8210         {
8211                 t->currenttexmatrix = r_waterscrollmatrix;
8212                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8213         }
8214         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8215         {
8216                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8217                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8218         }
8219
8220         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8221                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8222         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8223                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8224
8225         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8226         if (t->currentskinframe->qpixels)
8227                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8228         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8229         if (!t->basetexture)
8230                 t->basetexture = r_texture_notexture;
8231         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8232         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8233         t->nmaptexture = t->currentskinframe->nmap;
8234         if (!t->nmaptexture)
8235                 t->nmaptexture = r_texture_blanknormalmap;
8236         t->glosstexture = r_texture_black;
8237         t->glowtexture = t->currentskinframe->glow;
8238         t->fogtexture = t->currentskinframe->fog;
8239         t->reflectmasktexture = t->currentskinframe->reflect;
8240         if (t->backgroundnumskinframes)
8241         {
8242                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8243                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8244                 t->backgroundglosstexture = r_texture_black;
8245                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8246                 if (!t->backgroundnmaptexture)
8247                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8248                 // make sure that if glow is going to be used, both textures are not NULL
8249                 if (!t->backgroundglowtexture && t->glowtexture)
8250                         t->backgroundglowtexture = r_texture_black;
8251                 if (!t->glowtexture && t->backgroundglowtexture)
8252                         t->glowtexture = r_texture_black;
8253         }
8254         else
8255         {
8256                 t->backgroundbasetexture = r_texture_white;
8257                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8258                 t->backgroundglosstexture = r_texture_black;
8259                 t->backgroundglowtexture = NULL;
8260         }
8261         t->specularpower = r_shadow_glossexponent.value;
8262         // TODO: store reference values for these in the texture?
8263         t->specularscale = 0;
8264         if (r_shadow_gloss.integer > 0)
8265         {
8266                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8267                 {
8268                         if (r_shadow_glossintensity.value > 0)
8269                         {
8270                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8271                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8272                                 t->specularscale = r_shadow_glossintensity.value;
8273                         }
8274                 }
8275                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8276                 {
8277                         t->glosstexture = r_texture_white;
8278                         t->backgroundglosstexture = r_texture_white;
8279                         t->specularscale = r_shadow_gloss2intensity.value;
8280                         t->specularpower = r_shadow_gloss2exponent.value;
8281                 }
8282         }
8283         t->specularscale *= t->specularscalemod;
8284         t->specularpower *= t->specularpowermod;
8285         t->rtlightambient = 0;
8286
8287         // lightmaps mode looks bad with dlights using actual texturing, so turn
8288         // off the colormap and glossmap, but leave the normalmap on as it still
8289         // accurately represents the shading involved
8290         if (gl_lightmaps.integer)
8291         {
8292                 t->basetexture = r_texture_grey128;
8293                 t->pantstexture = r_texture_black;
8294                 t->shirttexture = r_texture_black;
8295                 if (gl_lightmaps.integer < 2)
8296                         t->nmaptexture = r_texture_blanknormalmap;
8297                 t->glosstexture = r_texture_black;
8298                 t->glowtexture = NULL;
8299                 t->fogtexture = NULL;
8300                 t->reflectmasktexture = NULL;
8301                 t->backgroundbasetexture = NULL;
8302                 if (gl_lightmaps.integer < 2)
8303                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8304                 t->backgroundglosstexture = r_texture_black;
8305                 t->backgroundglowtexture = NULL;
8306                 t->specularscale = 0;
8307                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8308         }
8309
8310         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8311         VectorClear(t->dlightcolor);
8312         t->currentnumlayers = 0;
8313         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8314         {
8315                 int blendfunc1, blendfunc2;
8316                 qboolean depthmask;
8317                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8318                 {
8319                         blendfunc1 = GL_SRC_ALPHA;
8320                         blendfunc2 = GL_ONE;
8321                 }
8322                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8323                 {
8324                         blendfunc1 = GL_SRC_ALPHA;
8325                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8326                 }
8327                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8328                 {
8329                         blendfunc1 = t->customblendfunc[0];
8330                         blendfunc2 = t->customblendfunc[1];
8331                 }
8332                 else
8333                 {
8334                         blendfunc1 = GL_ONE;
8335                         blendfunc2 = GL_ZERO;
8336                 }
8337                 // don't colormod evilblend textures
8338                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8339                         VectorSet(t->lightmapcolor, 1, 1, 1);
8340                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8341                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8342                 {
8343                         // fullbright is not affected by r_refdef.lightmapintensity
8344                         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]);
8345                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8346                                 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]);
8347                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8348                                 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]);
8349                 }
8350                 else
8351                 {
8352                         vec3_t ambientcolor;
8353                         float colorscale;
8354                         // set the color tint used for lights affecting this surface
8355                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8356                         colorscale = 2;
8357                         // q3bsp has no lightmap updates, so the lightstylevalue that
8358                         // would normally be baked into the lightmap must be
8359                         // applied to the color
8360                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8361                         if (model->type == mod_brushq3)
8362                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8363                         colorscale *= r_refdef.lightmapintensity;
8364                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8365                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8366                         // basic lit geometry
8367                         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]);
8368                         // add pants/shirt if needed
8369                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8370                                 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]);
8371                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8372                                 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]);
8373                         // now add ambient passes if needed
8374                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8375                         {
8376                                 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]);
8377                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8378                                         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]);
8379                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8380                                         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]);
8381                         }
8382                 }
8383                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8384                         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]);
8385                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8386                 {
8387                         // if this is opaque use alpha blend which will darken the earlier
8388                         // passes cheaply.
8389                         //
8390                         // if this is an alpha blended material, all the earlier passes
8391                         // were darkened by fog already, so we only need to add the fog
8392                         // color ontop through the fog mask texture
8393                         //
8394                         // if this is an additive blended material, all the earlier passes
8395                         // were darkened by fog already, and we should not add fog color
8396                         // (because the background was not darkened, there is no fog color
8397                         // that was lost behind it).
8398                         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]);
8399                 }
8400         }
8401
8402         return t->currentframe;
8403 }
8404
8405 rsurfacestate_t rsurface;
8406
8407 void RSurf_ActiveWorldEntity(void)
8408 {
8409         dp_model_t *model = r_refdef.scene.worldmodel;
8410         //if (rsurface.entity == r_refdef.scene.worldentity)
8411         //      return;
8412         rsurface.entity = r_refdef.scene.worldentity;
8413         rsurface.skeleton = NULL;
8414         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8415         rsurface.ent_skinnum = 0;
8416         rsurface.ent_qwskin = -1;
8417         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8418         rsurface.shadertime = r_refdef.scene.time;
8419         rsurface.matrix = identitymatrix;
8420         rsurface.inversematrix = identitymatrix;
8421         rsurface.matrixscale = 1;
8422         rsurface.inversematrixscale = 1;
8423         R_EntityMatrix(&identitymatrix);
8424         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8425         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8426         rsurface.fograngerecip = r_refdef.fograngerecip;
8427         rsurface.fogheightfade = r_refdef.fogheightfade;
8428         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8429         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8430         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8431         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8432         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8433         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8434         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8435         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8436         rsurface.colormod[3] = 1;
8437         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);
8438         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8439         rsurface.frameblend[0].lerp = 1;
8440         rsurface.ent_alttextures = false;
8441         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8442         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8443         rsurface.entityskeletaltransform3x4 = NULL;
8444         rsurface.entityskeletaltransform3x4buffer = NULL;
8445         rsurface.entityskeletaltransform3x4offset = 0;
8446         rsurface.entityskeletaltransform3x4size = 0;;
8447         rsurface.entityskeletalnumtransforms = 0;
8448         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8449         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8450         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8451         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8452         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8453         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8454         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8455         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8456         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8457         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8458         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8459         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8460         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8461         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8462         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8463         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8464         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8465         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8466         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8467         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8468         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8469         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8470         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8471         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8472         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8473         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8475         rsurface.modelelement3i = model->surfmesh.data_element3i;
8476         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8477         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8478         rsurface.modelelement3s = model->surfmesh.data_element3s;
8479         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8480         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8481         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8482         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8483         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8484         rsurface.modelsurfaces = model->data_surfaces;
8485         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8486         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8487         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8488         rsurface.modelgeneratedvertex = false;
8489         rsurface.batchgeneratedvertex = false;
8490         rsurface.batchfirstvertex = 0;
8491         rsurface.batchnumvertices = 0;
8492         rsurface.batchfirsttriangle = 0;
8493         rsurface.batchnumtriangles = 0;
8494         rsurface.batchvertex3f  = NULL;
8495         rsurface.batchvertex3f_vertexbuffer = NULL;
8496         rsurface.batchvertex3f_bufferoffset = 0;
8497         rsurface.batchsvector3f = NULL;
8498         rsurface.batchsvector3f_vertexbuffer = NULL;
8499         rsurface.batchsvector3f_bufferoffset = 0;
8500         rsurface.batchtvector3f = NULL;
8501         rsurface.batchtvector3f_vertexbuffer = NULL;
8502         rsurface.batchtvector3f_bufferoffset = 0;
8503         rsurface.batchnormal3f  = NULL;
8504         rsurface.batchnormal3f_vertexbuffer = NULL;
8505         rsurface.batchnormal3f_bufferoffset = 0;
8506         rsurface.batchlightmapcolor4f = NULL;
8507         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8508         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8509         rsurface.batchtexcoordtexture2f = NULL;
8510         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8511         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8512         rsurface.batchtexcoordlightmap2f = NULL;
8513         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8514         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8515         rsurface.batchskeletalindex4ub = NULL;
8516         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8517         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8518         rsurface.batchskeletalweight4ub = NULL;
8519         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8520         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8521         rsurface.batchvertexmesh = NULL;
8522         rsurface.batchvertexmeshbuffer = NULL;
8523         rsurface.batchvertex3fbuffer = NULL;
8524         rsurface.batchelement3i = NULL;
8525         rsurface.batchelement3i_indexbuffer = NULL;
8526         rsurface.batchelement3i_bufferoffset = 0;
8527         rsurface.batchelement3s = NULL;
8528         rsurface.batchelement3s_indexbuffer = NULL;
8529         rsurface.batchelement3s_bufferoffset = 0;
8530         rsurface.passcolor4f = NULL;
8531         rsurface.passcolor4f_vertexbuffer = NULL;
8532         rsurface.passcolor4f_bufferoffset = 0;
8533         rsurface.forcecurrenttextureupdate = false;
8534 }
8535
8536 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8537 {
8538         dp_model_t *model = ent->model;
8539         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8540         //      return;
8541         rsurface.entity = (entity_render_t *)ent;
8542         rsurface.skeleton = ent->skeleton;
8543         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8544         rsurface.ent_skinnum = ent->skinnum;
8545         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;
8546         rsurface.ent_flags = ent->flags;
8547         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8548         rsurface.matrix = ent->matrix;
8549         rsurface.inversematrix = ent->inversematrix;
8550         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8551         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8552         R_EntityMatrix(&rsurface.matrix);
8553         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8554         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8555         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8556         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8557         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8558         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8559         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8560         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8561         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8562         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8563         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8564         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8565         rsurface.colormod[3] = ent->alpha;
8566         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8567         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8568         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8569         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8570         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8571         if (ent->model->brush.submodel && !prepass)
8572         {
8573                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8574                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8575         }
8576         // if the animcache code decided it should use the shader path, skip the deform step
8577         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8578         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8579         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8580         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8581         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8582         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8583         {
8584                 if (ent->animcache_vertex3f)
8585                 {
8586                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8587                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8588                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8589                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8590                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8591                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8592                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8593                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8594                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8595                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8596                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8597                 }
8598                 else if (wanttangents)
8599                 {
8600                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8601                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8602                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8603                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8604                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8605                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8606                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8607                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8608                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8609                         rsurface.modelvertexmesh = NULL;
8610                         rsurface.modelvertexmeshbuffer = NULL;
8611                         rsurface.modelvertex3fbuffer = NULL;
8612                 }
8613                 else if (wantnormals)
8614                 {
8615                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8616                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8617                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8618                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8619                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8620                         rsurface.modelsvector3f = NULL;
8621                         rsurface.modeltvector3f = NULL;
8622                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8623                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8624                         rsurface.modelvertexmesh = NULL;
8625                         rsurface.modelvertexmeshbuffer = NULL;
8626                         rsurface.modelvertex3fbuffer = NULL;
8627                 }
8628                 else
8629                 {
8630                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8631                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8632                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8633                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8634                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8635                         rsurface.modelsvector3f = NULL;
8636                         rsurface.modeltvector3f = NULL;
8637                         rsurface.modelnormal3f = NULL;
8638                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8639                         rsurface.modelvertexmesh = NULL;
8640                         rsurface.modelvertexmeshbuffer = NULL;
8641                         rsurface.modelvertex3fbuffer = NULL;
8642                 }
8643                 rsurface.modelvertex3f_vertexbuffer = 0;
8644                 rsurface.modelvertex3f_bufferoffset = 0;
8645                 rsurface.modelsvector3f_vertexbuffer = 0;
8646                 rsurface.modelsvector3f_bufferoffset = 0;
8647                 rsurface.modeltvector3f_vertexbuffer = 0;
8648                 rsurface.modeltvector3f_bufferoffset = 0;
8649                 rsurface.modelnormal3f_vertexbuffer = 0;
8650                 rsurface.modelnormal3f_bufferoffset = 0;
8651                 rsurface.modelgeneratedvertex = true;
8652         }
8653         else
8654         {
8655                 if (rsurface.entityskeletaltransform3x4)
8656                 {
8657                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8658                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8659                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8660                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8661                 }
8662                 else
8663                 {
8664                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8665                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8666                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8667                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8668                 }
8669                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8670                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8671                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8672                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8673                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8674                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8675                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8676                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8677                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8678                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8679                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8680                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8681                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8682                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8683                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8684                 rsurface.modelgeneratedvertex = false;
8685         }
8686         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8687         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8688         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8689         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8690         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8691         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8692         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8693         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8694         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8695         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8696         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8697         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8698         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8699         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8700         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8701         rsurface.modelelement3i = model->surfmesh.data_element3i;
8702         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8703         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8704         rsurface.modelelement3s = model->surfmesh.data_element3s;
8705         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8706         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8707         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8708         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8709         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8710         rsurface.modelsurfaces = model->data_surfaces;
8711         rsurface.batchgeneratedvertex = false;
8712         rsurface.batchfirstvertex = 0;
8713         rsurface.batchnumvertices = 0;
8714         rsurface.batchfirsttriangle = 0;
8715         rsurface.batchnumtriangles = 0;
8716         rsurface.batchvertex3f  = NULL;
8717         rsurface.batchvertex3f_vertexbuffer = NULL;
8718         rsurface.batchvertex3f_bufferoffset = 0;
8719         rsurface.batchsvector3f = NULL;
8720         rsurface.batchsvector3f_vertexbuffer = NULL;
8721         rsurface.batchsvector3f_bufferoffset = 0;
8722         rsurface.batchtvector3f = NULL;
8723         rsurface.batchtvector3f_vertexbuffer = NULL;
8724         rsurface.batchtvector3f_bufferoffset = 0;
8725         rsurface.batchnormal3f  = NULL;
8726         rsurface.batchnormal3f_vertexbuffer = NULL;
8727         rsurface.batchnormal3f_bufferoffset = 0;
8728         rsurface.batchlightmapcolor4f = NULL;
8729         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8730         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8731         rsurface.batchtexcoordtexture2f = NULL;
8732         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8733         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8734         rsurface.batchtexcoordlightmap2f = NULL;
8735         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8736         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8737         rsurface.batchskeletalindex4ub = NULL;
8738         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8739         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8740         rsurface.batchskeletalweight4ub = NULL;
8741         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8742         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8743         rsurface.batchvertexmesh = NULL;
8744         rsurface.batchvertexmeshbuffer = NULL;
8745         rsurface.batchvertex3fbuffer = NULL;
8746         rsurface.batchelement3i = NULL;
8747         rsurface.batchelement3i_indexbuffer = NULL;
8748         rsurface.batchelement3i_bufferoffset = 0;
8749         rsurface.batchelement3s = NULL;
8750         rsurface.batchelement3s_indexbuffer = NULL;
8751         rsurface.batchelement3s_bufferoffset = 0;
8752         rsurface.passcolor4f = NULL;
8753         rsurface.passcolor4f_vertexbuffer = NULL;
8754         rsurface.passcolor4f_bufferoffset = 0;
8755         rsurface.forcecurrenttextureupdate = false;
8756 }
8757
8758 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)
8759 {
8760         rsurface.entity = r_refdef.scene.worldentity;
8761         rsurface.skeleton = NULL;
8762         rsurface.ent_skinnum = 0;
8763         rsurface.ent_qwskin = -1;
8764         rsurface.ent_flags = entflags;
8765         rsurface.shadertime = r_refdef.scene.time - shadertime;
8766         rsurface.modelnumvertices = numvertices;
8767         rsurface.modelnumtriangles = numtriangles;
8768         rsurface.matrix = *matrix;
8769         rsurface.inversematrix = *inversematrix;
8770         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8771         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8772         R_EntityMatrix(&rsurface.matrix);
8773         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8774         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8775         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8776         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8777         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8778         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8779         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8780         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8781         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8782         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8783         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8784         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8785         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);
8786         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8787         rsurface.frameblend[0].lerp = 1;
8788         rsurface.ent_alttextures = false;
8789         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8790         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8791         rsurface.entityskeletaltransform3x4 = NULL;
8792         rsurface.entityskeletaltransform3x4buffer = NULL;
8793         rsurface.entityskeletaltransform3x4offset = 0;
8794         rsurface.entityskeletaltransform3x4size = 0;
8795         rsurface.entityskeletalnumtransforms = 0;
8796         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8797         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8798         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8799         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8800         if (wanttangents)
8801         {
8802                 rsurface.modelvertex3f = (float *)vertex3f;
8803                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8804                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8805                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8806         }
8807         else if (wantnormals)
8808         {
8809                 rsurface.modelvertex3f = (float *)vertex3f;
8810                 rsurface.modelsvector3f = NULL;
8811                 rsurface.modeltvector3f = NULL;
8812                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8813         }
8814         else
8815         {
8816                 rsurface.modelvertex3f = (float *)vertex3f;
8817                 rsurface.modelsvector3f = NULL;
8818                 rsurface.modeltvector3f = NULL;
8819                 rsurface.modelnormal3f = NULL;
8820         }
8821         rsurface.modelvertexmesh = NULL;
8822         rsurface.modelvertexmeshbuffer = NULL;
8823         rsurface.modelvertex3fbuffer = NULL;
8824         rsurface.modelvertex3f_vertexbuffer = 0;
8825         rsurface.modelvertex3f_bufferoffset = 0;
8826         rsurface.modelsvector3f_vertexbuffer = 0;
8827         rsurface.modelsvector3f_bufferoffset = 0;
8828         rsurface.modeltvector3f_vertexbuffer = 0;
8829         rsurface.modeltvector3f_bufferoffset = 0;
8830         rsurface.modelnormal3f_vertexbuffer = 0;
8831         rsurface.modelnormal3f_bufferoffset = 0;
8832         rsurface.modelgeneratedvertex = true;
8833         rsurface.modellightmapcolor4f  = (float *)color4f;
8834         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8835         rsurface.modellightmapcolor4f_bufferoffset = 0;
8836         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8837         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8838         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8839         rsurface.modeltexcoordlightmap2f  = NULL;
8840         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8841         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8842         rsurface.modelskeletalindex4ub = NULL;
8843         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8844         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8845         rsurface.modelskeletalweight4ub = NULL;
8846         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8847         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8848         rsurface.modelelement3i = (int *)element3i;
8849         rsurface.modelelement3i_indexbuffer = NULL;
8850         rsurface.modelelement3i_bufferoffset = 0;
8851         rsurface.modelelement3s = (unsigned short *)element3s;
8852         rsurface.modelelement3s_indexbuffer = NULL;
8853         rsurface.modelelement3s_bufferoffset = 0;
8854         rsurface.modellightmapoffsets = NULL;
8855         rsurface.modelsurfaces = NULL;
8856         rsurface.batchgeneratedvertex = false;
8857         rsurface.batchfirstvertex = 0;
8858         rsurface.batchnumvertices = 0;
8859         rsurface.batchfirsttriangle = 0;
8860         rsurface.batchnumtriangles = 0;
8861         rsurface.batchvertex3f  = NULL;
8862         rsurface.batchvertex3f_vertexbuffer = NULL;
8863         rsurface.batchvertex3f_bufferoffset = 0;
8864         rsurface.batchsvector3f = NULL;
8865         rsurface.batchsvector3f_vertexbuffer = NULL;
8866         rsurface.batchsvector3f_bufferoffset = 0;
8867         rsurface.batchtvector3f = NULL;
8868         rsurface.batchtvector3f_vertexbuffer = NULL;
8869         rsurface.batchtvector3f_bufferoffset = 0;
8870         rsurface.batchnormal3f  = NULL;
8871         rsurface.batchnormal3f_vertexbuffer = NULL;
8872         rsurface.batchnormal3f_bufferoffset = 0;
8873         rsurface.batchlightmapcolor4f = NULL;
8874         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8875         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8876         rsurface.batchtexcoordtexture2f = NULL;
8877         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8878         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8879         rsurface.batchtexcoordlightmap2f = NULL;
8880         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8881         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8882         rsurface.batchskeletalindex4ub = NULL;
8883         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8884         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8885         rsurface.batchskeletalweight4ub = NULL;
8886         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8887         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8888         rsurface.batchvertexmesh = NULL;
8889         rsurface.batchvertexmeshbuffer = NULL;
8890         rsurface.batchvertex3fbuffer = NULL;
8891         rsurface.batchelement3i = NULL;
8892         rsurface.batchelement3i_indexbuffer = NULL;
8893         rsurface.batchelement3i_bufferoffset = 0;
8894         rsurface.batchelement3s = NULL;
8895         rsurface.batchelement3s_indexbuffer = NULL;
8896         rsurface.batchelement3s_bufferoffset = 0;
8897         rsurface.passcolor4f = NULL;
8898         rsurface.passcolor4f_vertexbuffer = NULL;
8899         rsurface.passcolor4f_bufferoffset = 0;
8900         rsurface.forcecurrenttextureupdate = true;
8901
8902         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8903         {
8904                 if ((wantnormals || wanttangents) && !normal3f)
8905                 {
8906                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8907                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8908                 }
8909                 if (wanttangents && !svector3f)
8910                 {
8911                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8912                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8913                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8914                 }
8915         }
8916 }
8917
8918 float RSurf_FogPoint(const float *v)
8919 {
8920         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8921         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8922         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8923         float FogHeightFade = r_refdef.fogheightfade;
8924         float fogfrac;
8925         unsigned int fogmasktableindex;
8926         if (r_refdef.fogplaneviewabove)
8927                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8928         else
8929                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8930         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8931         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8932 }
8933
8934 float RSurf_FogVertex(const float *v)
8935 {
8936         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8937         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8938         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8939         float FogHeightFade = rsurface.fogheightfade;
8940         float fogfrac;
8941         unsigned int fogmasktableindex;
8942         if (r_refdef.fogplaneviewabove)
8943                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8944         else
8945                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8946         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8947         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8948 }
8949
8950 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8951 {
8952         int i;
8953         for (i = 0;i < numelements;i++)
8954                 outelement3i[i] = inelement3i[i] + adjust;
8955 }
8956
8957 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8958 extern cvar_t gl_vbo;
8959 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8960 {
8961         int deformindex;
8962         int firsttriangle;
8963         int numtriangles;
8964         int firstvertex;
8965         int endvertex;
8966         int numvertices;
8967         int surfacefirsttriangle;
8968         int surfacenumtriangles;
8969         int surfacefirstvertex;
8970         int surfaceendvertex;
8971         int surfacenumvertices;
8972         int batchnumsurfaces = texturenumsurfaces;
8973         int batchnumvertices;
8974         int batchnumtriangles;
8975         int needsupdate;
8976         int i, j;
8977         qboolean gaps;
8978         qboolean dynamicvertex;
8979         float amplitude;
8980         float animpos;
8981         float scale;
8982         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8983         float waveparms[4];
8984         unsigned char *ub;
8985         q3shaderinfo_deform_t *deform;
8986         const msurface_t *surface, *firstsurface;
8987         r_vertexmesh_t *vertexmesh;
8988         if (!texturenumsurfaces)
8989                 return;
8990         // find vertex range of this surface batch
8991         gaps = false;
8992         firstsurface = texturesurfacelist[0];
8993         firsttriangle = firstsurface->num_firsttriangle;
8994         batchnumvertices = 0;
8995         batchnumtriangles = 0;
8996         firstvertex = endvertex = firstsurface->num_firstvertex;
8997         for (i = 0;i < texturenumsurfaces;i++)
8998         {
8999                 surface = texturesurfacelist[i];
9000                 if (surface != firstsurface + i)
9001                         gaps = true;
9002                 surfacefirstvertex = surface->num_firstvertex;
9003                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9004                 surfacenumvertices = surface->num_vertices;
9005                 surfacenumtriangles = surface->num_triangles;
9006                 if (firstvertex > surfacefirstvertex)
9007                         firstvertex = surfacefirstvertex;
9008                 if (endvertex < surfaceendvertex)
9009                         endvertex = surfaceendvertex;
9010                 batchnumvertices += surfacenumvertices;
9011                 batchnumtriangles += surfacenumtriangles;
9012         }
9013
9014         r_refdef.stats[r_stat_batch_batches]++;
9015         if (gaps)
9016                 r_refdef.stats[r_stat_batch_withgaps]++;
9017         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9018         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9019         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9020
9021         // we now know the vertex range used, and if there are any gaps in it
9022         rsurface.batchfirstvertex = firstvertex;
9023         rsurface.batchnumvertices = endvertex - firstvertex;
9024         rsurface.batchfirsttriangle = firsttriangle;
9025         rsurface.batchnumtriangles = batchnumtriangles;
9026
9027         // this variable holds flags for which properties have been updated that
9028         // may require regenerating vertexmesh array...
9029         needsupdate = 0;
9030
9031         // check if any dynamic vertex processing must occur
9032         dynamicvertex = false;
9033
9034         // a cvar to force the dynamic vertex path to be taken, for debugging
9035         if (r_batch_debugdynamicvertexpath.integer)
9036         {
9037                 if (!dynamicvertex)
9038                 {
9039                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9040                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9041                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9042                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9043                 }
9044                 dynamicvertex = true;
9045         }
9046
9047         // if there is a chance of animated vertex colors, it's a dynamic batch
9048         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9049         {
9050                 if (!dynamicvertex)
9051                 {
9052                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9053                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9054                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9055                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9056                 }
9057                 dynamicvertex = true;
9058                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9059         }
9060
9061         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9062         {
9063                 switch (deform->deform)
9064                 {
9065                 default:
9066                 case Q3DEFORM_PROJECTIONSHADOW:
9067                 case Q3DEFORM_TEXT0:
9068                 case Q3DEFORM_TEXT1:
9069                 case Q3DEFORM_TEXT2:
9070                 case Q3DEFORM_TEXT3:
9071                 case Q3DEFORM_TEXT4:
9072                 case Q3DEFORM_TEXT5:
9073                 case Q3DEFORM_TEXT6:
9074                 case Q3DEFORM_TEXT7:
9075                 case Q3DEFORM_NONE:
9076                         break;
9077                 case Q3DEFORM_AUTOSPRITE:
9078                         if (!dynamicvertex)
9079                         {
9080                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9081                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9082                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9083                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9084                         }
9085                         dynamicvertex = true;
9086                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9087                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9088                         break;
9089                 case Q3DEFORM_AUTOSPRITE2:
9090                         if (!dynamicvertex)
9091                         {
9092                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9093                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9094                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9095                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9096                         }
9097                         dynamicvertex = true;
9098                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9099                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9100                         break;
9101                 case Q3DEFORM_NORMAL:
9102                         if (!dynamicvertex)
9103                         {
9104                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9105                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9106                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9107                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9108                         }
9109                         dynamicvertex = true;
9110                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9111                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9112                         break;
9113                 case Q3DEFORM_WAVE:
9114                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9115                                 break; // if wavefunc is a nop, ignore this transform
9116                         if (!dynamicvertex)
9117                         {
9118                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9119                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9120                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9121                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9122                         }
9123                         dynamicvertex = true;
9124                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9125                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9126                         break;
9127                 case Q3DEFORM_BULGE:
9128                         if (!dynamicvertex)
9129                         {
9130                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9131                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9132                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9133                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9134                         }
9135                         dynamicvertex = true;
9136                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9137                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9138                         break;
9139                 case Q3DEFORM_MOVE:
9140                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9141                                 break; // if wavefunc is a nop, ignore this transform
9142                         if (!dynamicvertex)
9143                         {
9144                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9145                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9146                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9147                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9148                         }
9149                         dynamicvertex = true;
9150                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9151                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9152                         break;
9153                 }
9154         }
9155         switch(rsurface.texture->tcgen.tcgen)
9156         {
9157         default:
9158         case Q3TCGEN_TEXTURE:
9159                 break;
9160         case Q3TCGEN_LIGHTMAP:
9161                 if (!dynamicvertex)
9162                 {
9163                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9164                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9165                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9166                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9167                 }
9168                 dynamicvertex = true;
9169                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9170                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9171                 break;
9172         case Q3TCGEN_VECTOR:
9173                 if (!dynamicvertex)
9174                 {
9175                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9176                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9177                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9178                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9179                 }
9180                 dynamicvertex = true;
9181                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9182                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9183                 break;
9184         case Q3TCGEN_ENVIRONMENT:
9185                 if (!dynamicvertex)
9186                 {
9187                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9188                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9189                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9190                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9191                 }
9192                 dynamicvertex = true;
9193                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9194                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9195                 break;
9196         }
9197         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9198         {
9199                 if (!dynamicvertex)
9200                 {
9201                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9202                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9203                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9204                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9205                 }
9206                 dynamicvertex = true;
9207                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9208                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9209         }
9210
9211         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9212         {
9213                 if (!dynamicvertex)
9214                 {
9215                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9216                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9217                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9218                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9219                 }
9220                 dynamicvertex = true;
9221                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9222         }
9223
9224         // when the model data has no vertex buffer (dynamic mesh), we need to
9225         // eliminate gaps
9226         if (vid.useinterleavedarrays && !rsurface.modelvertexmeshbuffer)
9227                 batchneed |= BATCHNEED_NOGAPS;
9228
9229         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9230         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9231         // we ensure this by treating the vertex batch as dynamic...
9232         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9233         {
9234                 if (!dynamicvertex)
9235                 {
9236                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9237                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9238                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9239                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9240                 }
9241                 dynamicvertex = true;
9242         }
9243
9244         if (dynamicvertex)
9245         {
9246                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9247                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9248                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9249                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9250                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9251                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9252                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9253                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9254         }
9255
9256         // if needsupdate, we have to do a dynamic vertex batch for sure
9257         if (needsupdate & batchneed)
9258         {
9259                 if (!dynamicvertex)
9260                 {
9261                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9262                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9263                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9264                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9265                 }
9266                 dynamicvertex = true;
9267         }
9268
9269         // see if we need to build vertexmesh from arrays
9270         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9271         {
9272                 if (!dynamicvertex)
9273                 {
9274                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9275                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9276                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9277                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9278                 }
9279                 dynamicvertex = true;
9280         }
9281
9282         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9283         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9284                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9285
9286         rsurface.batchvertex3f = rsurface.modelvertex3f;
9287         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9288         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9289         rsurface.batchsvector3f = rsurface.modelsvector3f;
9290         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9291         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9292         rsurface.batchtvector3f = rsurface.modeltvector3f;
9293         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9294         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9295         rsurface.batchnormal3f = rsurface.modelnormal3f;
9296         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9297         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9298         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9299         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9300         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9301         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9302         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9303         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9304         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9305         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9306         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9307         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9308         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9309         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9310         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9311         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9312         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9313         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
9314         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9315         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
9316         rsurface.batchelement3i = rsurface.modelelement3i;
9317         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9318         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9319         rsurface.batchelement3s = rsurface.modelelement3s;
9320         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9321         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9322         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9323         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9324         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9325         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9326         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9327
9328         // if any dynamic vertex processing has to occur in software, we copy the
9329         // entire surface list together before processing to rebase the vertices
9330         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9331         //
9332         // if any gaps exist and we do not have a static vertex buffer, we have to
9333         // copy the surface list together to avoid wasting upload bandwidth on the
9334         // vertices in the gaps.
9335         //
9336         // if gaps exist and we have a static vertex buffer, we can choose whether
9337         // to combine the index buffer ranges into one dynamic index buffer or
9338         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9339         //
9340         // in many cases the batch is reduced to one draw call.
9341
9342         rsurface.batchmultidraw = false;
9343         rsurface.batchmultidrawnumsurfaces = 0;
9344         rsurface.batchmultidrawsurfacelist = NULL;
9345
9346         if (!dynamicvertex)
9347         {
9348                 // static vertex data, just set pointers...
9349                 rsurface.batchgeneratedvertex = false;
9350                 // if there are gaps, we want to build a combined index buffer,
9351                 // otherwise use the original static buffer with an appropriate offset
9352                 if (gaps)
9353                 {
9354                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9355                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9356                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9357                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9358                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9359                         {
9360                                 rsurface.batchmultidraw = true;
9361                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9362                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9363                                 return;
9364                         }
9365                         // build a new triangle elements array for this batch
9366                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9367                         rsurface.batchfirsttriangle = 0;
9368                         numtriangles = 0;
9369                         for (i = 0;i < texturenumsurfaces;i++)
9370                         {
9371                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9372                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9373                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9374                                 numtriangles += surfacenumtriangles;
9375                         }
9376                         rsurface.batchelement3i_indexbuffer = NULL;
9377                         rsurface.batchelement3i_bufferoffset = 0;
9378                         rsurface.batchelement3s = NULL;
9379                         rsurface.batchelement3s_indexbuffer = NULL;
9380                         rsurface.batchelement3s_bufferoffset = 0;
9381                         if (endvertex <= 65536)
9382                         {
9383                                 // make a 16bit (unsigned short) index array if possible
9384                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9385                                 for (i = 0;i < numtriangles*3;i++)
9386                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9387                         }
9388                 }
9389                 else
9390                 {
9391                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9392                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9393                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9394                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9395                 }
9396                 return;
9397         }
9398
9399         // something needs software processing, do it for real...
9400         // we only directly handle separate array data in this case and then
9401         // generate interleaved data if needed...
9402         rsurface.batchgeneratedvertex = true;
9403         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9404         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9405         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9406         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9407
9408         // now copy the vertex data into a combined array and make an index array
9409         // (this is what Quake3 does all the time)
9410         // we also apply any skeletal animation here that would have been done in
9411         // the vertex shader, because most of the dynamic vertex animation cases
9412         // need actual vertex positions and normals
9413         //if (dynamicvertex)
9414         {
9415                 rsurface.batchvertex3fbuffer = NULL;
9416                 rsurface.batchvertexmesh = NULL;
9417                 rsurface.batchvertexmeshbuffer = NULL;
9418                 rsurface.batchvertex3f = NULL;
9419                 rsurface.batchvertex3f_vertexbuffer = NULL;
9420                 rsurface.batchvertex3f_bufferoffset = 0;
9421                 rsurface.batchsvector3f = NULL;
9422                 rsurface.batchsvector3f_vertexbuffer = NULL;
9423                 rsurface.batchsvector3f_bufferoffset = 0;
9424                 rsurface.batchtvector3f = NULL;
9425                 rsurface.batchtvector3f_vertexbuffer = NULL;
9426                 rsurface.batchtvector3f_bufferoffset = 0;
9427                 rsurface.batchnormal3f = NULL;
9428                 rsurface.batchnormal3f_vertexbuffer = NULL;
9429                 rsurface.batchnormal3f_bufferoffset = 0;
9430                 rsurface.batchlightmapcolor4f = NULL;
9431                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9432                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9433                 rsurface.batchtexcoordtexture2f = NULL;
9434                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9435                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9436                 rsurface.batchtexcoordlightmap2f = NULL;
9437                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9438                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9439                 rsurface.batchskeletalindex4ub = NULL;
9440                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9441                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9442                 rsurface.batchskeletalweight4ub = NULL;
9443                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9444                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9445                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9446                 rsurface.batchelement3i_indexbuffer = NULL;
9447                 rsurface.batchelement3i_bufferoffset = 0;
9448                 rsurface.batchelement3s = NULL;
9449                 rsurface.batchelement3s_indexbuffer = NULL;
9450                 rsurface.batchelement3s_bufferoffset = 0;
9451                 rsurface.batchskeletaltransform3x4buffer = NULL;
9452                 rsurface.batchskeletaltransform3x4offset = 0;
9453                 rsurface.batchskeletaltransform3x4size = 0;
9454                 // we'll only be setting up certain arrays as needed
9455                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9456                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9457                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9458                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9459                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9460                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9461                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9462                 {
9463                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9464                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9465                 }
9466                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9467                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9468                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9469                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9470                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9471                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9472                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9473                 {
9474                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9475                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9476                 }
9477                 numvertices = 0;
9478                 numtriangles = 0;
9479                 for (i = 0;i < texturenumsurfaces;i++)
9480                 {
9481                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9482                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9483                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9484                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9485                         // copy only the data requested
9486                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9487                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9488                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9489                         {
9490                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9491                                 {
9492                                         if (rsurface.batchvertex3f)
9493                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9494                                         else
9495                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9496                                 }
9497                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9498                                 {
9499                                         if (rsurface.modelnormal3f)
9500                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9501                                         else
9502                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9503                                 }
9504                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9505                                 {
9506                                         if (rsurface.modelsvector3f)
9507                                         {
9508                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9509                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9510                                         }
9511                                         else
9512                                         {
9513                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9514                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9515                                         }
9516                                 }
9517                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9518                                 {
9519                                         if (rsurface.modellightmapcolor4f)
9520                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9521                                         else
9522                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9523                                 }
9524                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9525                                 {
9526                                         if (rsurface.modeltexcoordtexture2f)
9527                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9528                                         else
9529                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9530                                 }
9531                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9532                                 {
9533                                         if (rsurface.modeltexcoordlightmap2f)
9534                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9535                                         else
9536                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9537                                 }
9538                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9539                                 {
9540                                         if (rsurface.modelskeletalindex4ub)
9541                                         {
9542                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9543                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9544                                         }
9545                                         else
9546                                         {
9547                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9548                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9549                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9550                                                 for (j = 0;j < surfacenumvertices;j++)
9551                                                         ub[j*4] = 255;
9552                                         }
9553                                 }
9554                         }
9555                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9556                         numvertices += surfacenumvertices;
9557                         numtriangles += surfacenumtriangles;
9558                 }
9559
9560                 // generate a 16bit index array as well if possible
9561                 // (in general, dynamic batches fit)
9562                 if (numvertices <= 65536)
9563                 {
9564                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9565                         for (i = 0;i < numtriangles*3;i++)
9566                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9567                 }
9568
9569                 // since we've copied everything, the batch now starts at 0
9570                 rsurface.batchfirstvertex = 0;
9571                 rsurface.batchnumvertices = batchnumvertices;
9572                 rsurface.batchfirsttriangle = 0;
9573                 rsurface.batchnumtriangles = batchnumtriangles;
9574         }
9575
9576         // apply skeletal animation that would have been done in the vertex shader
9577         if (rsurface.batchskeletaltransform3x4)
9578         {
9579                 const unsigned char *si;
9580                 const unsigned char *sw;
9581                 const float *t[4];
9582                 const float *b = rsurface.batchskeletaltransform3x4;
9583                 float *vp, *vs, *vt, *vn;
9584                 float w[4];
9585                 float m[3][4], n[3][4];
9586                 float tp[3], ts[3], tt[3], tn[3];
9587                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9588                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9589                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9590                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9591                 si = rsurface.batchskeletalindex4ub;
9592                 sw = rsurface.batchskeletalweight4ub;
9593                 vp = rsurface.batchvertex3f;
9594                 vs = rsurface.batchsvector3f;
9595                 vt = rsurface.batchtvector3f;
9596                 vn = rsurface.batchnormal3f;
9597                 memset(m[0], 0, sizeof(m));
9598                 memset(n[0], 0, sizeof(n));
9599                 for (i = 0;i < batchnumvertices;i++)
9600                 {
9601                         t[0] = b + si[0]*12;
9602                         if (sw[0] == 255)
9603                         {
9604                                 // common case - only one matrix
9605                                 m[0][0] = t[0][ 0];
9606                                 m[0][1] = t[0][ 1];
9607                                 m[0][2] = t[0][ 2];
9608                                 m[0][3] = t[0][ 3];
9609                                 m[1][0] = t[0][ 4];
9610                                 m[1][1] = t[0][ 5];
9611                                 m[1][2] = t[0][ 6];
9612                                 m[1][3] = t[0][ 7];
9613                                 m[2][0] = t[0][ 8];
9614                                 m[2][1] = t[0][ 9];
9615                                 m[2][2] = t[0][10];
9616                                 m[2][3] = t[0][11];
9617                         }
9618                         else if (sw[2] + sw[3])
9619                         {
9620                                 // blend 4 matrices
9621                                 t[1] = b + si[1]*12;
9622                                 t[2] = b + si[2]*12;
9623                                 t[3] = b + si[3]*12;
9624                                 w[0] = sw[0] * (1.0f / 255.0f);
9625                                 w[1] = sw[1] * (1.0f / 255.0f);
9626                                 w[2] = sw[2] * (1.0f / 255.0f);
9627                                 w[3] = sw[3] * (1.0f / 255.0f);
9628                                 // blend the matrices
9629                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9630                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9631                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9632                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9633                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9634                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9635                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9636                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9637                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9638                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9639                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9640                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9641                         }
9642                         else
9643                         {
9644                                 // blend 2 matrices
9645                                 t[1] = b + si[1]*12;
9646                                 w[0] = sw[0] * (1.0f / 255.0f);
9647                                 w[1] = sw[1] * (1.0f / 255.0f);
9648                                 // blend the matrices
9649                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9650                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9651                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9652                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9653                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9654                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9655                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9656                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9657                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9658                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9659                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9660                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9661                         }
9662                         si += 4;
9663                         sw += 4;
9664                         // modify the vertex
9665                         VectorCopy(vp, tp);
9666                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9667                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9668                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9669                         vp += 3;
9670                         if (vn)
9671                         {
9672                                 // the normal transformation matrix is a set of cross products...
9673                                 CrossProduct(m[1], m[2], n[0]);
9674                                 CrossProduct(m[2], m[0], n[1]);
9675                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9676                                 VectorCopy(vn, tn);
9677                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9678                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9679                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9680                                 VectorNormalize(vn);
9681                                 vn += 3;
9682                                 if (vs)
9683                                 {
9684                                         VectorCopy(vs, ts);
9685                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9686                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9687                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9688                                         VectorNormalize(vs);
9689                                         vs += 3;
9690                                         VectorCopy(vt, tt);
9691                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9692                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9693                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9694                                         VectorNormalize(vt);
9695                                         vt += 3;
9696                                 }
9697                         }
9698                 }
9699                 rsurface.batchskeletaltransform3x4 = NULL;
9700                 rsurface.batchskeletalnumtransforms = 0;
9701         }
9702
9703         // q1bsp surfaces rendered in vertex color mode have to have colors
9704         // calculated based on lightstyles
9705         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9706         {
9707                 // generate color arrays for the surfaces in this list
9708                 int c[4];
9709                 int scale;
9710                 int size3;
9711                 const int *offsets;
9712                 const unsigned char *lm;
9713                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9714                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9715                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9716                 numvertices = 0;
9717                 for (i = 0;i < texturenumsurfaces;i++)
9718                 {
9719                         surface = texturesurfacelist[i];
9720                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9721                         surfacenumvertices = surface->num_vertices;
9722                         if (surface->lightmapinfo->samples)
9723                         {
9724                                 for (j = 0;j < surfacenumvertices;j++)
9725                                 {
9726                                         lm = surface->lightmapinfo->samples + offsets[j];
9727                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9728                                         VectorScale(lm, scale, c);
9729                                         if (surface->lightmapinfo->styles[1] != 255)
9730                                         {
9731                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9732                                                 lm += size3;
9733                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9734                                                 VectorMA(c, scale, lm, c);
9735                                                 if (surface->lightmapinfo->styles[2] != 255)
9736                                                 {
9737                                                         lm += size3;
9738                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9739                                                         VectorMA(c, scale, lm, c);
9740                                                         if (surface->lightmapinfo->styles[3] != 255)
9741                                                         {
9742                                                                 lm += size3;
9743                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9744                                                                 VectorMA(c, scale, lm, c);
9745                                                         }
9746                                                 }
9747                                         }
9748                                         c[0] >>= 7;
9749                                         c[1] >>= 7;
9750                                         c[2] >>= 7;
9751                                         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);
9752                                         numvertices++;
9753                                 }
9754                         }
9755                         else
9756                         {
9757                                 for (j = 0;j < surfacenumvertices;j++)
9758                                 {
9759                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9760                                         numvertices++;
9761                                 }
9762                         }
9763                 }
9764         }
9765
9766         // if vertices are deformed (sprite flares and things in maps, possibly
9767         // water waves, bulges and other deformations), modify the copied vertices
9768         // in place
9769         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9770         {
9771                 switch (deform->deform)
9772                 {
9773                 default:
9774                 case Q3DEFORM_PROJECTIONSHADOW:
9775                 case Q3DEFORM_TEXT0:
9776                 case Q3DEFORM_TEXT1:
9777                 case Q3DEFORM_TEXT2:
9778                 case Q3DEFORM_TEXT3:
9779                 case Q3DEFORM_TEXT4:
9780                 case Q3DEFORM_TEXT5:
9781                 case Q3DEFORM_TEXT6:
9782                 case Q3DEFORM_TEXT7:
9783                 case Q3DEFORM_NONE:
9784                         break;
9785                 case Q3DEFORM_AUTOSPRITE:
9786                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9787                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9788                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9789                         VectorNormalize(newforward);
9790                         VectorNormalize(newright);
9791                         VectorNormalize(newup);
9792 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9793 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9794 //                      rsurface.batchvertex3f_bufferoffset = 0;
9795 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9796 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9797 //                      rsurface.batchsvector3f_bufferoffset = 0;
9798 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9799 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9800 //                      rsurface.batchtvector3f_bufferoffset = 0;
9801 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9802 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9803 //                      rsurface.batchnormal3f_bufferoffset = 0;
9804                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9805                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9806                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9807                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9808                                 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);
9809                         // a single autosprite surface can contain multiple sprites...
9810                         for (j = 0;j < batchnumvertices - 3;j += 4)
9811                         {
9812                                 VectorClear(center);
9813                                 for (i = 0;i < 4;i++)
9814                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9815                                 VectorScale(center, 0.25f, center);
9816                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9817                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9818                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9819                                 for (i = 0;i < 4;i++)
9820                                 {
9821                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9822                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9823                                 }
9824                         }
9825                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9826                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9827                         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);
9828                         break;
9829                 case Q3DEFORM_AUTOSPRITE2:
9830                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9831                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9832                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9833                         VectorNormalize(newforward);
9834                         VectorNormalize(newright);
9835                         VectorNormalize(newup);
9836 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9837 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9838 //                      rsurface.batchvertex3f_bufferoffset = 0;
9839                         {
9840                                 const float *v1, *v2;
9841                                 vec3_t start, end;
9842                                 float f, l;
9843                                 struct
9844                                 {
9845                                         float length2;
9846                                         const float *v1;
9847                                         const float *v2;
9848                                 }
9849                                 shortest[2];
9850                                 memset(shortest, 0, sizeof(shortest));
9851                                 // a single autosprite surface can contain multiple sprites...
9852                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9853                                 {
9854                                         VectorClear(center);
9855                                         for (i = 0;i < 4;i++)
9856                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9857                                         VectorScale(center, 0.25f, center);
9858                                         // find the two shortest edges, then use them to define the
9859                                         // axis vectors for rotating around the central axis
9860                                         for (i = 0;i < 6;i++)
9861                                         {
9862                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9863                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9864                                                 l = VectorDistance2(v1, v2);
9865                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9866                                                 if (v1[2] != v2[2])
9867                                                         l += (1.0f / 1024.0f);
9868                                                 if (shortest[0].length2 > l || i == 0)
9869                                                 {
9870                                                         shortest[1] = shortest[0];
9871                                                         shortest[0].length2 = l;
9872                                                         shortest[0].v1 = v1;
9873                                                         shortest[0].v2 = v2;
9874                                                 }
9875                                                 else if (shortest[1].length2 > l || i == 1)
9876                                                 {
9877                                                         shortest[1].length2 = l;
9878                                                         shortest[1].v1 = v1;
9879                                                         shortest[1].v2 = v2;
9880                                                 }
9881                                         }
9882                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9883                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9884                                         // this calculates the right vector from the shortest edge
9885                                         // and the up vector from the edge midpoints
9886                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9887                                         VectorNormalize(right);
9888                                         VectorSubtract(end, start, up);
9889                                         VectorNormalize(up);
9890                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9891                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9892                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9893                                         VectorNegate(forward, forward);
9894                                         VectorReflect(forward, 0, up, forward);
9895                                         VectorNormalize(forward);
9896                                         CrossProduct(up, forward, newright);
9897                                         VectorNormalize(newright);
9898                                         // rotate the quad around the up axis vector, this is made
9899                                         // especially easy by the fact we know the quad is flat,
9900                                         // so we only have to subtract the center position and
9901                                         // measure distance along the right vector, and then
9902                                         // multiply that by the newright vector and add back the
9903                                         // center position
9904                                         // we also need to subtract the old position to undo the
9905                                         // displacement from the center, which we do with a
9906                                         // DotProduct, the subtraction/addition of center is also
9907                                         // optimized into DotProducts here
9908                                         l = DotProduct(right, center);
9909                                         for (i = 0;i < 4;i++)
9910                                         {
9911                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9912                                                 f = DotProduct(right, v1) - l;
9913                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9914                                         }
9915                                 }
9916                         }
9917                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9918                         {
9919 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9920 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9921 //                              rsurface.batchnormal3f_bufferoffset = 0;
9922                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9923                         }
9924                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9925                         {
9926 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9927 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9928 //                              rsurface.batchsvector3f_bufferoffset = 0;
9929 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9930 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9931 //                              rsurface.batchtvector3f_bufferoffset = 0;
9932                                 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);
9933                         }
9934                         break;
9935                 case Q3DEFORM_NORMAL:
9936                         // deform the normals to make reflections wavey
9937                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9938                         rsurface.batchnormal3f_vertexbuffer = NULL;
9939                         rsurface.batchnormal3f_bufferoffset = 0;
9940                         for (j = 0;j < batchnumvertices;j++)
9941                         {
9942                                 float vertex[3];
9943                                 float *normal = rsurface.batchnormal3f + 3*j;
9944                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9945                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9946                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9947                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9948                                 VectorNormalize(normal);
9949                         }
9950                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9951                         {
9952 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9953 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9954 //                              rsurface.batchsvector3f_bufferoffset = 0;
9955 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9956 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9957 //                              rsurface.batchtvector3f_bufferoffset = 0;
9958                                 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);
9959                         }
9960                         break;
9961                 case Q3DEFORM_WAVE:
9962                         // deform vertex array to make wavey water and flags and such
9963                         waveparms[0] = deform->waveparms[0];
9964                         waveparms[1] = deform->waveparms[1];
9965                         waveparms[2] = deform->waveparms[2];
9966                         waveparms[3] = deform->waveparms[3];
9967                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9968                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9969                         // this is how a divisor of vertex influence on deformation
9970                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9971                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9972 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9973 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9974 //                      rsurface.batchvertex3f_bufferoffset = 0;
9975 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9976 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9977 //                      rsurface.batchnormal3f_bufferoffset = 0;
9978                         for (j = 0;j < batchnumvertices;j++)
9979                         {
9980                                 // if the wavefunc depends on time, evaluate it per-vertex
9981                                 if (waveparms[3])
9982                                 {
9983                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9984                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9985                                 }
9986                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9987                         }
9988                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9989                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9990                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9991                         {
9992 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9993 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9994 //                              rsurface.batchsvector3f_bufferoffset = 0;
9995 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9996 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9997 //                              rsurface.batchtvector3f_bufferoffset = 0;
9998                                 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);
9999                         }
10000                         break;
10001                 case Q3DEFORM_BULGE:
10002                         // deform vertex array to make the surface have moving bulges
10003 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10004 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10005 //                      rsurface.batchvertex3f_bufferoffset = 0;
10006 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10007 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10008 //                      rsurface.batchnormal3f_bufferoffset = 0;
10009                         for (j = 0;j < batchnumvertices;j++)
10010                         {
10011                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10012                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10013                         }
10014                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10015                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10016                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10017                         {
10018 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10019 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10020 //                              rsurface.batchsvector3f_bufferoffset = 0;
10021 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10022 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10023 //                              rsurface.batchtvector3f_bufferoffset = 0;
10024                                 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);
10025                         }
10026                         break;
10027                 case Q3DEFORM_MOVE:
10028                         // deform vertex array
10029                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10030                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10031                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10032                         VectorScale(deform->parms, scale, waveparms);
10033 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10034 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10035 //                      rsurface.batchvertex3f_bufferoffset = 0;
10036                         for (j = 0;j < batchnumvertices;j++)
10037                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10038                         break;
10039                 }
10040         }
10041
10042         // generate texcoords based on the chosen texcoord source
10043         switch(rsurface.texture->tcgen.tcgen)
10044         {
10045         default:
10046         case Q3TCGEN_TEXTURE:
10047                 break;
10048         case Q3TCGEN_LIGHTMAP:
10049 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10050 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10051 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10052                 if (rsurface.batchtexcoordlightmap2f)
10053                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10054                 break;
10055         case Q3TCGEN_VECTOR:
10056 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10057 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10058 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10059                 for (j = 0;j < batchnumvertices;j++)
10060                 {
10061                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10062                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10063                 }
10064                 break;
10065         case Q3TCGEN_ENVIRONMENT:
10066                 // make environment reflections using a spheremap
10067                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10068                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10069                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10070                 for (j = 0;j < batchnumvertices;j++)
10071                 {
10072                         // identical to Q3A's method, but executed in worldspace so
10073                         // carried models can be shiny too
10074
10075                         float viewer[3], d, reflected[3], worldreflected[3];
10076
10077                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10078                         // VectorNormalize(viewer);
10079
10080                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10081
10082                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10083                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10084                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10085                         // note: this is proportinal to viewer, so we can normalize later
10086
10087                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10088                         VectorNormalize(worldreflected);
10089
10090                         // note: this sphere map only uses world x and z!
10091                         // so positive and negative y will LOOK THE SAME.
10092                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10093                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10094                 }
10095                 break;
10096         }
10097         // the only tcmod that needs software vertex processing is turbulent, so
10098         // check for it here and apply the changes if needed
10099         // and we only support that as the first one
10100         // (handling a mixture of turbulent and other tcmods would be problematic
10101         //  without punting it entirely to a software path)
10102         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10103         {
10104                 amplitude = rsurface.texture->tcmods[0].parms[1];
10105                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10106 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10107 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10108 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10109                 for (j = 0;j < batchnumvertices;j++)
10110                 {
10111                         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);
10112                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10113                 }
10114         }
10115
10116         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10117         {
10118                 // convert the modified arrays to vertex structs
10119 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10120 //              rsurface.batchvertexmeshbuffer = NULL;
10121                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10122                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10123                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10124                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10125                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10126                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10127                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10128                 {
10129                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10130                         {
10131                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10132                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10133                         }
10134                 }
10135                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10136                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10137                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10138                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10139                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10140                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10141                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10142                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10143                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10144                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10145                 {
10146                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10147                         {
10148                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10149                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10150                         }
10151                 }
10152         }
10153 }
10154
10155 void RSurf_DrawBatch(void)
10156 {
10157         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10158         // through the pipeline, killing it earlier in the pipeline would have
10159         // per-surface overhead rather than per-batch overhead, so it's best to
10160         // reject it here, before it hits glDraw.
10161         if (rsurface.batchnumtriangles == 0)
10162                 return;
10163 #if 0
10164         // batch debugging code
10165         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10166         {
10167                 int i;
10168                 int j;
10169                 int c;
10170                 const int *e;
10171                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10172                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10173                 {
10174                         c = e[i];
10175                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10176                         {
10177                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10178                                 {
10179                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10180                                                 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);
10181                                         break;
10182                                 }
10183                         }
10184                 }
10185         }
10186 #endif
10187         if (rsurface.batchmultidraw)
10188         {
10189                 // issue multiple draws rather than copying index data
10190                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10191                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10192                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10193                 for (i = 0;i < numsurfaces;)
10194                 {
10195                         // combine consecutive surfaces as one draw
10196                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10197                                 if (surfacelist[j] != surfacelist[k] + 1)
10198                                         break;
10199                         firstvertex = surfacelist[i]->num_firstvertex;
10200                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10201                         firsttriangle = surfacelist[i]->num_firsttriangle;
10202                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10203                         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);
10204                         i = j;
10205                 }
10206         }
10207         else
10208         {
10209                 // there is only one consecutive run of index data (may have been combined)
10210                 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);
10211         }
10212 }
10213
10214 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10215 {
10216         // pick the closest matching water plane
10217         int planeindex, vertexindex, bestplaneindex = -1;
10218         float d, bestd;
10219         vec3_t vert;
10220         const float *v;
10221         r_waterstate_waterplane_t *p;
10222         qboolean prepared = false;
10223         bestd = 0;
10224         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10225         {
10226                 if(p->camera_entity != rsurface.texture->camera_entity)
10227                         continue;
10228                 d = 0;
10229                 if(!prepared)
10230                 {
10231                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10232                         prepared = true;
10233                         if(rsurface.batchnumvertices == 0)
10234                                 break;
10235                 }
10236                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10237                 {
10238                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10239                         d += fabs(PlaneDiff(vert, &p->plane));
10240                 }
10241                 if (bestd > d || bestplaneindex < 0)
10242                 {
10243                         bestd = d;
10244                         bestplaneindex = planeindex;
10245                 }
10246         }
10247         return bestplaneindex;
10248         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10249         // this situation though, as it might be better to render single larger
10250         // batches with useless stuff (backface culled for example) than to
10251         // render multiple smaller batches
10252 }
10253
10254 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10255 {
10256         int i;
10257         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10258         rsurface.passcolor4f_vertexbuffer = 0;
10259         rsurface.passcolor4f_bufferoffset = 0;
10260         for (i = 0;i < rsurface.batchnumvertices;i++)
10261                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10262 }
10263
10264 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10265 {
10266         int i;
10267         float f;
10268         const float *v;
10269         const float *c;
10270         float *c2;
10271         if (rsurface.passcolor4f)
10272         {
10273                 // generate color arrays
10274                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10275                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10276                 rsurface.passcolor4f_vertexbuffer = 0;
10277                 rsurface.passcolor4f_bufferoffset = 0;
10278                 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)
10279                 {
10280                         f = RSurf_FogVertex(v);
10281                         c2[0] = c[0] * f;
10282                         c2[1] = c[1] * f;
10283                         c2[2] = c[2] * f;
10284                         c2[3] = c[3];
10285                 }
10286         }
10287         else
10288         {
10289                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10290                 rsurface.passcolor4f_vertexbuffer = 0;
10291                 rsurface.passcolor4f_bufferoffset = 0;
10292                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10293                 {
10294                         f = RSurf_FogVertex(v);
10295                         c2[0] = f;
10296                         c2[1] = f;
10297                         c2[2] = f;
10298                         c2[3] = 1;
10299                 }
10300         }
10301 }
10302
10303 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10304 {
10305         int i;
10306         float f;
10307         const float *v;
10308         const float *c;
10309         float *c2;
10310         if (!rsurface.passcolor4f)
10311                 return;
10312         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10313         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10314         rsurface.passcolor4f_vertexbuffer = 0;
10315         rsurface.passcolor4f_bufferoffset = 0;
10316         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)
10317         {
10318                 f = RSurf_FogVertex(v);
10319                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10320                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10321                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10322                 c2[3] = c[3];
10323         }
10324 }
10325
10326 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10327 {
10328         int i;
10329         const float *c;
10330         float *c2;
10331         if (!rsurface.passcolor4f)
10332                 return;
10333         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10334         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10335         rsurface.passcolor4f_vertexbuffer = 0;
10336         rsurface.passcolor4f_bufferoffset = 0;
10337         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10338         {
10339                 c2[0] = c[0] * r;
10340                 c2[1] = c[1] * g;
10341                 c2[2] = c[2] * b;
10342                 c2[3] = c[3] * a;
10343         }
10344 }
10345
10346 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10347 {
10348         int i;
10349         const float *c;
10350         float *c2;
10351         if (!rsurface.passcolor4f)
10352                 return;
10353         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10354         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10355         rsurface.passcolor4f_vertexbuffer = 0;
10356         rsurface.passcolor4f_bufferoffset = 0;
10357         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10358         {
10359                 c2[0] = c[0] + r_refdef.scene.ambient;
10360                 c2[1] = c[1] + r_refdef.scene.ambient;
10361                 c2[2] = c[2] + r_refdef.scene.ambient;
10362                 c2[3] = c[3];
10363         }
10364 }
10365
10366 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10367 {
10368         // TODO: optimize
10369         rsurface.passcolor4f = NULL;
10370         rsurface.passcolor4f_vertexbuffer = 0;
10371         rsurface.passcolor4f_bufferoffset = 0;
10372         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10373         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10374         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10375         GL_Color(r, g, b, a);
10376         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10377         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10378         R_Mesh_TexMatrix(0, NULL);
10379         RSurf_DrawBatch();
10380 }
10381
10382 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10383 {
10384         // TODO: optimize applyfog && applycolor case
10385         // just apply fog if necessary, and tint the fog color array if necessary
10386         rsurface.passcolor4f = NULL;
10387         rsurface.passcolor4f_vertexbuffer = 0;
10388         rsurface.passcolor4f_bufferoffset = 0;
10389         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10390         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10391         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10392         GL_Color(r, g, b, a);
10393         RSurf_DrawBatch();
10394 }
10395
10396 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10397 {
10398         // TODO: optimize
10399         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10400         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10401         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10402         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10403         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10404         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10405         GL_Color(r, g, b, a);
10406         RSurf_DrawBatch();
10407 }
10408
10409 static void RSurf_DrawBatch_GL11_ClampColor(void)
10410 {
10411         int i;
10412         const float *c1;
10413         float *c2;
10414         if (!rsurface.passcolor4f)
10415                 return;
10416         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10417         {
10418                 c2[0] = bound(0.0f, c1[0], 1.0f);
10419                 c2[1] = bound(0.0f, c1[1], 1.0f);
10420                 c2[2] = bound(0.0f, c1[2], 1.0f);
10421                 c2[3] = bound(0.0f, c1[3], 1.0f);
10422         }
10423 }
10424
10425 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10426 {
10427         int i;
10428         float f;
10429         const float *v;
10430         const float *n;
10431         float *c;
10432         //vec3_t eyedir;
10433
10434         // fake shading
10435         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10436         rsurface.passcolor4f_vertexbuffer = 0;
10437         rsurface.passcolor4f_bufferoffset = 0;
10438         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)
10439         {
10440                 f = -DotProduct(r_refdef.view.forward, n);
10441                 f = max(0, f);
10442                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10443                 f *= r_refdef.lightmapintensity;
10444                 Vector4Set(c, f, f, f, 1);
10445         }
10446 }
10447
10448 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10449 {
10450         RSurf_DrawBatch_GL11_ApplyFakeLight();
10451         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10452         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10453         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10454         GL_Color(r, g, b, a);
10455         RSurf_DrawBatch();
10456 }
10457
10458 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10459 {
10460         int i;
10461         float f;
10462         float alpha;
10463         const float *v;
10464         const float *n;
10465         float *c;
10466         vec3_t ambientcolor;
10467         vec3_t diffusecolor;
10468         vec3_t lightdir;
10469         // TODO: optimize
10470         // model lighting
10471         VectorCopy(rsurface.modellight_lightdir, lightdir);
10472         f = 0.5f * r_refdef.lightmapintensity;
10473         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10474         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10475         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10476         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10477         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10478         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10479         alpha = *a;
10480         if (VectorLength2(diffusecolor) > 0)
10481         {
10482                 // q3-style directional shading
10483                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10484                 rsurface.passcolor4f_vertexbuffer = 0;
10485                 rsurface.passcolor4f_bufferoffset = 0;
10486                 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)
10487                 {
10488                         if ((f = DotProduct(n, lightdir)) > 0)
10489                                 VectorMA(ambientcolor, f, diffusecolor, c);
10490                         else
10491                                 VectorCopy(ambientcolor, c);
10492                         c[3] = alpha;
10493                 }
10494                 *r = 1;
10495                 *g = 1;
10496                 *b = 1;
10497                 *a = 1;
10498                 *applycolor = false;
10499         }
10500         else
10501         {
10502                 *r = ambientcolor[0];
10503                 *g = ambientcolor[1];
10504                 *b = ambientcolor[2];
10505                 rsurface.passcolor4f = NULL;
10506                 rsurface.passcolor4f_vertexbuffer = 0;
10507                 rsurface.passcolor4f_bufferoffset = 0;
10508         }
10509 }
10510
10511 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10512 {
10513         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10514         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10515         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10516         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10517         GL_Color(r, g, b, a);
10518         RSurf_DrawBatch();
10519 }
10520
10521 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10522 {
10523         int i;
10524         float f;
10525         const float *v;
10526         float *c;
10527
10528         // fake shading
10529         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10530         rsurface.passcolor4f_vertexbuffer = 0;
10531         rsurface.passcolor4f_bufferoffset = 0;
10532
10533         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10534         {
10535                 f = 1 - RSurf_FogVertex(v);
10536                 c[0] = r;
10537                 c[1] = g;
10538                 c[2] = b;
10539                 c[3] = f * a;
10540         }
10541 }
10542
10543 void RSurf_SetupDepthAndCulling(void)
10544 {
10545         // submodels are biased to avoid z-fighting with world surfaces that they
10546         // may be exactly overlapping (avoids z-fighting artifacts on certain
10547         // doors and things in Quake maps)
10548         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10549         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10550         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10551         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10552 }
10553
10554 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10555 {
10556         // transparent sky would be ridiculous
10557         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10558                 return;
10559         R_SetupShader_Generic_NoTexture(false, false);
10560         skyrenderlater = true;
10561         RSurf_SetupDepthAndCulling();
10562         GL_DepthMask(true);
10563         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10564         // skymasking on them, and Quake3 never did sky masking (unlike
10565         // software Quake and software Quake2), so disable the sky masking
10566         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10567         // and skymasking also looks very bad when noclipping outside the
10568         // level, so don't use it then either.
10569         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10570         {
10571                 R_Mesh_ResetTextureState();
10572                 if (skyrendermasked)
10573                 {
10574                         R_SetupShader_DepthOrShadow(false, false, false);
10575                         // depth-only (masking)
10576                         GL_ColorMask(0,0,0,0);
10577                         // just to make sure that braindead drivers don't draw
10578                         // anything despite that colormask...
10579                         GL_BlendFunc(GL_ZERO, GL_ONE);
10580                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10581                         if (rsurface.batchvertex3fbuffer)
10582                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10583                         else
10584                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10585                 }
10586                 else
10587                 {
10588                         R_SetupShader_Generic_NoTexture(false, false);
10589                         // fog sky
10590                         GL_BlendFunc(GL_ONE, GL_ZERO);
10591                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10592                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10593                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10594                 }
10595                 RSurf_DrawBatch();
10596                 if (skyrendermasked)
10597                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10598         }
10599         R_Mesh_ResetTextureState();
10600         GL_Color(1, 1, 1, 1);
10601 }
10602
10603 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10604 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10605 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10606 {
10607         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10608                 return;
10609         if (prepass)
10610         {
10611                 // render screenspace normalmap to texture
10612                 GL_DepthMask(true);
10613                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10614                 RSurf_DrawBatch();
10615                 return;
10616         }
10617
10618         // bind lightmap texture
10619
10620         // water/refraction/reflection/camera surfaces have to be handled specially
10621         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10622         {
10623                 int start, end, startplaneindex;
10624                 for (start = 0;start < texturenumsurfaces;start = end)
10625                 {
10626                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10627                         if(startplaneindex < 0)
10628                         {
10629                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10630                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10631                                 end = start + 1;
10632                                 continue;
10633                         }
10634                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10635                                 ;
10636                         // now that we have a batch using the same planeindex, render it
10637                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10638                         {
10639                                 // render water or distortion background
10640                                 GL_DepthMask(true);
10641                                 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);
10642                                 RSurf_DrawBatch();
10643                                 // blend surface on top
10644                                 GL_DepthMask(false);
10645                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10646                                 RSurf_DrawBatch();
10647                         }
10648                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10649                         {
10650                                 // render surface with reflection texture as input
10651                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10652                                 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);
10653                                 RSurf_DrawBatch();
10654                         }
10655                 }
10656                 return;
10657         }
10658
10659         // render surface batch normally
10660         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10661         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);
10662         RSurf_DrawBatch();
10663 }
10664
10665 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10666 {
10667         // OpenGL 1.3 path - anything not completely ancient
10668         qboolean applycolor;
10669         qboolean applyfog;
10670         int layerindex;
10671         const texturelayer_t *layer;
10672         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);
10673         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10674
10675         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10676         {
10677                 vec4_t layercolor;
10678                 int layertexrgbscale;
10679                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10680                 {
10681                         if (layerindex == 0)
10682                                 GL_AlphaTest(true);
10683                         else
10684                         {
10685                                 GL_AlphaTest(false);
10686                                 GL_DepthFunc(GL_EQUAL);
10687                         }
10688                 }
10689                 GL_DepthMask(layer->depthmask && writedepth);
10690                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10691                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10692                 {
10693                         layertexrgbscale = 4;
10694                         VectorScale(layer->color, 0.25f, layercolor);
10695                 }
10696                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10697                 {
10698                         layertexrgbscale = 2;
10699                         VectorScale(layer->color, 0.5f, layercolor);
10700                 }
10701                 else
10702                 {
10703                         layertexrgbscale = 1;
10704                         VectorScale(layer->color, 1.0f, layercolor);
10705                 }
10706                 layercolor[3] = layer->color[3];
10707                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10708                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10709                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10710                 switch (layer->type)
10711                 {
10712                 case TEXTURELAYERTYPE_LITTEXTURE:
10713                         // single-pass lightmapped texture with 2x rgbscale
10714                         R_Mesh_TexBind(0, r_texture_white);
10715                         R_Mesh_TexMatrix(0, NULL);
10716                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10717                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10718                         R_Mesh_TexBind(1, layer->texture);
10719                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10720                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10721                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10722                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10723                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10724                         else if (FAKELIGHT_ENABLED)
10725                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10726                         else if (rsurface.uselightmaptexture)
10727                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10728                         else
10729                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10730                         break;
10731                 case TEXTURELAYERTYPE_TEXTURE:
10732                         // singletexture unlit texture with transparency support
10733                         R_Mesh_TexBind(0, layer->texture);
10734                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10735                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10736                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10737                         R_Mesh_TexBind(1, 0);
10738                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10739                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10740                         break;
10741                 case TEXTURELAYERTYPE_FOG:
10742                         // singletexture fogging
10743                         if (layer->texture)
10744                         {
10745                                 R_Mesh_TexBind(0, layer->texture);
10746                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10747                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10748                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10749                         }
10750                         else
10751                         {
10752                                 R_Mesh_TexBind(0, 0);
10753                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10754                         }
10755                         R_Mesh_TexBind(1, 0);
10756                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10757                         // generate a color array for the fog pass
10758                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10759                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10760                         RSurf_DrawBatch();
10761                         break;
10762                 default:
10763                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10764                 }
10765         }
10766         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10767         {
10768                 GL_DepthFunc(GL_LEQUAL);
10769                 GL_AlphaTest(false);
10770         }
10771 }
10772
10773 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10774 {
10775         // OpenGL 1.1 - crusty old voodoo path
10776         qboolean applyfog;
10777         int layerindex;
10778         const texturelayer_t *layer;
10779         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);
10780         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10781
10782         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10783         {
10784                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10785                 {
10786                         if (layerindex == 0)
10787                                 GL_AlphaTest(true);
10788                         else
10789                         {
10790                                 GL_AlphaTest(false);
10791                                 GL_DepthFunc(GL_EQUAL);
10792                         }
10793                 }
10794                 GL_DepthMask(layer->depthmask && writedepth);
10795                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10796                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10797                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10798                 switch (layer->type)
10799                 {
10800                 case TEXTURELAYERTYPE_LITTEXTURE:
10801                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10802                         {
10803                                 // two-pass lit texture with 2x rgbscale
10804                                 // first the lightmap pass
10805                                 R_Mesh_TexBind(0, r_texture_white);
10806                                 R_Mesh_TexMatrix(0, NULL);
10807                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10808                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10809                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10810                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10811                                 else if (FAKELIGHT_ENABLED)
10812                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10813                                 else if (rsurface.uselightmaptexture)
10814                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10815                                 else
10816                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10817                                 // then apply the texture to it
10818                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10819                                 R_Mesh_TexBind(0, layer->texture);
10820                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10821                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10822                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10823                                 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);
10824                         }
10825                         else
10826                         {
10827                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10828                                 R_Mesh_TexBind(0, layer->texture);
10829                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10830                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10831                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10832                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10833                                         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);
10834                                 else if (FAKELIGHT_ENABLED)
10835                                         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);
10836                                 else
10837                                         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);
10838                         }
10839                         break;
10840                 case TEXTURELAYERTYPE_TEXTURE:
10841                         // singletexture unlit texture with transparency support
10842                         R_Mesh_TexBind(0, layer->texture);
10843                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10844                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10845                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10846                         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);
10847                         break;
10848                 case TEXTURELAYERTYPE_FOG:
10849                         // singletexture fogging
10850                         if (layer->texture)
10851                         {
10852                                 R_Mesh_TexBind(0, layer->texture);
10853                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10854                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10855                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10856                         }
10857                         else
10858                         {
10859                                 R_Mesh_TexBind(0, 0);
10860                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10861                         }
10862                         // generate a color array for the fog pass
10863                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10864                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10865                         RSurf_DrawBatch();
10866                         break;
10867                 default:
10868                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10869                 }
10870         }
10871         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10872         {
10873                 GL_DepthFunc(GL_LEQUAL);
10874                 GL_AlphaTest(false);
10875         }
10876 }
10877
10878 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10879 {
10880         int vi;
10881         int j;
10882         r_vertexgeneric_t *batchvertex;
10883         float c[4];
10884
10885 //      R_Mesh_ResetTextureState();
10886         R_SetupShader_Generic_NoTexture(false, false);
10887
10888         if(rsurface.texture && rsurface.texture->currentskinframe)
10889         {
10890                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10891                 c[3] *= rsurface.texture->currentalpha;
10892         }
10893         else
10894         {
10895                 c[0] = 1;
10896                 c[1] = 0;
10897                 c[2] = 1;
10898                 c[3] = 1;
10899         }
10900
10901         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10902         {
10903                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10904                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10905                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10906         }
10907
10908         // brighten it up (as texture value 127 means "unlit")
10909         c[0] *= 2 * r_refdef.view.colorscale;
10910         c[1] *= 2 * r_refdef.view.colorscale;
10911         c[2] *= 2 * r_refdef.view.colorscale;
10912
10913         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10914                 c[3] *= r_wateralpha.value;
10915
10916         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10917         {
10918                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10919                 GL_DepthMask(false);
10920         }
10921         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10922         {
10923                 GL_BlendFunc(GL_ONE, GL_ONE);
10924                 GL_DepthMask(false);
10925         }
10926         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10927         {
10928                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10929                 GL_DepthMask(false);
10930         }
10931         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10932         {
10933                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10934                 GL_DepthMask(false);
10935         }
10936         else
10937         {
10938                 GL_BlendFunc(GL_ONE, GL_ZERO);
10939                 GL_DepthMask(writedepth);
10940         }
10941
10942         if (r_showsurfaces.integer == 3)
10943         {
10944                 rsurface.passcolor4f = NULL;
10945
10946                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10947                 {
10948                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10949
10950                         rsurface.passcolor4f = NULL;
10951                         rsurface.passcolor4f_vertexbuffer = 0;
10952                         rsurface.passcolor4f_bufferoffset = 0;
10953                 }
10954                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10955                 {
10956                         qboolean applycolor = true;
10957                         float one = 1.0;
10958
10959                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10960
10961                         r_refdef.lightmapintensity = 1;
10962                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10963                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10964                 }
10965                 else if (FAKELIGHT_ENABLED)
10966                 {
10967                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10968
10969                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10970                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10971                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10972                 }
10973                 else
10974                 {
10975                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10976
10977                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10978                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10979                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10980                 }
10981
10982                 if(!rsurface.passcolor4f)
10983                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10984
10985                 RSurf_DrawBatch_GL11_ApplyAmbient();
10986                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10987                 if(r_refdef.fogenabled)
10988                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10989                 RSurf_DrawBatch_GL11_ClampColor();
10990
10991                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10992                 R_SetupShader_Generic_NoTexture(false, false);
10993                 RSurf_DrawBatch();
10994         }
10995         else if (!r_refdef.view.showdebug)
10996         {
10997                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10998                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10999                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11000                 {
11001                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11002                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11003                 }
11004                 R_Mesh_PrepareVertices_Generic_Unlock();
11005                 RSurf_DrawBatch();
11006         }
11007         else if (r_showsurfaces.integer == 4)
11008         {
11009                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11010                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11011                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11012                 {
11013                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11014                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11015                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11016                 }
11017                 R_Mesh_PrepareVertices_Generic_Unlock();
11018                 RSurf_DrawBatch();
11019         }
11020         else if (r_showsurfaces.integer == 2)
11021         {
11022                 const int *e;
11023                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11024                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11025                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11026                 {
11027                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11028                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11029                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11030                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11031                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11032                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11033                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11034                 }
11035                 R_Mesh_PrepareVertices_Generic_Unlock();
11036                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11037         }
11038         else
11039         {
11040                 int texturesurfaceindex;
11041                 int k;
11042                 const msurface_t *surface;
11043                 float surfacecolor4f[4];
11044                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11045                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11046                 vi = 0;
11047                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11048                 {
11049                         surface = texturesurfacelist[texturesurfaceindex];
11050                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11051                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11052                         for (j = 0;j < surface->num_vertices;j++)
11053                         {
11054                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11055                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11056                                 vi++;
11057                         }
11058                 }
11059                 R_Mesh_PrepareVertices_Generic_Unlock();
11060                 RSurf_DrawBatch();
11061         }
11062 }
11063
11064 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11065 {
11066         CHECKGLERROR
11067         RSurf_SetupDepthAndCulling();
11068         if (r_showsurfaces.integer)
11069         {
11070                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11071                 return;
11072         }
11073         switch (vid.renderpath)
11074         {
11075         case RENDERPATH_GL20:
11076         case RENDERPATH_D3D9:
11077         case RENDERPATH_D3D10:
11078         case RENDERPATH_D3D11:
11079         case RENDERPATH_SOFT:
11080         case RENDERPATH_GLES2:
11081                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11082                 break;
11083         case RENDERPATH_GL13:
11084         case RENDERPATH_GLES1:
11085                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11086                 break;
11087         case RENDERPATH_GL11:
11088                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11089                 break;
11090         }
11091         CHECKGLERROR
11092 }
11093
11094 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11095 {
11096         CHECKGLERROR
11097         RSurf_SetupDepthAndCulling();
11098         if (r_showsurfaces.integer)
11099         {
11100                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11101                 return;
11102         }
11103         switch (vid.renderpath)
11104         {
11105         case RENDERPATH_GL20:
11106         case RENDERPATH_D3D9:
11107         case RENDERPATH_D3D10:
11108         case RENDERPATH_D3D11:
11109         case RENDERPATH_SOFT:
11110         case RENDERPATH_GLES2:
11111                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11112                 break;
11113         case RENDERPATH_GL13:
11114         case RENDERPATH_GLES1:
11115                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11116                 break;
11117         case RENDERPATH_GL11:
11118                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11119                 break;
11120         }
11121         CHECKGLERROR
11122 }
11123
11124 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11125 {
11126         int i, j;
11127         int texturenumsurfaces, endsurface;
11128         texture_t *texture;
11129         const msurface_t *surface;
11130         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11131
11132         // if the model is static it doesn't matter what value we give for
11133         // wantnormals and wanttangents, so this logic uses only rules applicable
11134         // to a model, knowing that they are meaningless otherwise
11135         if (ent == r_refdef.scene.worldentity)
11136                 RSurf_ActiveWorldEntity();
11137         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11138                 RSurf_ActiveModelEntity(ent, false, false, false);
11139         else
11140         {
11141                 switch (vid.renderpath)
11142                 {
11143                 case RENDERPATH_GL20:
11144                 case RENDERPATH_D3D9:
11145                 case RENDERPATH_D3D10:
11146                 case RENDERPATH_D3D11:
11147                 case RENDERPATH_SOFT:
11148                 case RENDERPATH_GLES2:
11149                         RSurf_ActiveModelEntity(ent, true, true, false);
11150                         break;
11151                 case RENDERPATH_GL11:
11152                 case RENDERPATH_GL13:
11153                 case RENDERPATH_GLES1:
11154                         RSurf_ActiveModelEntity(ent, true, false, false);
11155                         break;
11156                 }
11157         }
11158
11159         if (r_transparentdepthmasking.integer)
11160         {
11161                 qboolean setup = false;
11162                 for (i = 0;i < numsurfaces;i = j)
11163                 {
11164                         j = i + 1;
11165                         surface = rsurface.modelsurfaces + surfacelist[i];
11166                         texture = surface->texture;
11167                         rsurface.texture = R_GetCurrentTexture(texture);
11168                         rsurface.lightmaptexture = NULL;
11169                         rsurface.deluxemaptexture = NULL;
11170                         rsurface.uselightmaptexture = false;
11171                         // scan ahead until we find a different texture
11172                         endsurface = min(i + 1024, numsurfaces);
11173                         texturenumsurfaces = 0;
11174                         texturesurfacelist[texturenumsurfaces++] = surface;
11175                         for (;j < endsurface;j++)
11176                         {
11177                                 surface = rsurface.modelsurfaces + surfacelist[j];
11178                                 if (texture != surface->texture)
11179                                         break;
11180                                 texturesurfacelist[texturenumsurfaces++] = surface;
11181                         }
11182                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11183                                 continue;
11184                         // render the range of surfaces as depth
11185                         if (!setup)
11186                         {
11187                                 setup = true;
11188                                 GL_ColorMask(0,0,0,0);
11189                                 GL_Color(1,1,1,1);
11190                                 GL_DepthTest(true);
11191                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11192                                 GL_DepthMask(true);
11193 //                              R_Mesh_ResetTextureState();
11194                         }
11195                         RSurf_SetupDepthAndCulling();
11196                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11197                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11198                         if (rsurface.batchvertex3fbuffer)
11199                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
11200                         else
11201                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
11202                         RSurf_DrawBatch();
11203                 }
11204                 if (setup)
11205                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11206         }
11207
11208         for (i = 0;i < numsurfaces;i = j)
11209         {
11210                 j = i + 1;
11211                 surface = rsurface.modelsurfaces + surfacelist[i];
11212                 texture = surface->texture;
11213                 rsurface.texture = R_GetCurrentTexture(texture);
11214                 // scan ahead until we find a different texture
11215                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11216                 texturenumsurfaces = 0;
11217                 texturesurfacelist[texturenumsurfaces++] = surface;
11218                 if(FAKELIGHT_ENABLED)
11219                 {
11220                         rsurface.lightmaptexture = NULL;
11221                         rsurface.deluxemaptexture = NULL;
11222                         rsurface.uselightmaptexture = false;
11223                         for (;j < endsurface;j++)
11224                         {
11225                                 surface = rsurface.modelsurfaces + surfacelist[j];
11226                                 if (texture != surface->texture)
11227                                         break;
11228                                 texturesurfacelist[texturenumsurfaces++] = surface;
11229                         }
11230                 }
11231                 else
11232                 {
11233                         rsurface.lightmaptexture = surface->lightmaptexture;
11234                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11235                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11236                         for (;j < endsurface;j++)
11237                         {
11238                                 surface = rsurface.modelsurfaces + surfacelist[j];
11239                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11240                                         break;
11241                                 texturesurfacelist[texturenumsurfaces++] = surface;
11242                         }
11243                 }
11244                 // render the range of surfaces
11245                 if (ent == r_refdef.scene.worldentity)
11246                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11247                 else
11248                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11249         }
11250         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11251 }
11252
11253 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11254 {
11255         // transparent surfaces get pushed off into the transparent queue
11256         int surfacelistindex;
11257         const msurface_t *surface;
11258         vec3_t tempcenter, center;
11259         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11260         {
11261                 surface = texturesurfacelist[surfacelistindex];
11262                 if (r_transparent_sortsurfacesbynearest.integer)
11263                 {
11264                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11265                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11266                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11267                 }
11268                 else
11269                 {
11270                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11271                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11272                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11273                 }
11274                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11275                 if (rsurface.entity->transparent_offset) // transparent offset
11276                 {
11277                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11278                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11279                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11280                 }
11281                 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);
11282         }
11283 }
11284
11285 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11286 {
11287         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11288                 return;
11289         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11290                 return;
11291         RSurf_SetupDepthAndCulling();
11292         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11293         if (rsurface.batchvertex3fbuffer)
11294                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
11295         else
11296                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
11297         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11298         RSurf_DrawBatch();
11299 }
11300
11301 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11302 {
11303         CHECKGLERROR
11304         if (depthonly)
11305                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11306         else if (prepass)
11307         {
11308                 if (!rsurface.texture->currentnumlayers)
11309                         return;
11310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11311                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11312                 else
11313                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11314         }
11315         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11316                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11317         else if (!rsurface.texture->currentnumlayers)
11318                 return;
11319         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11320         {
11321                 // in the deferred case, transparent surfaces were queued during prepass
11322                 if (!r_shadow_usingdeferredprepass)
11323                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11324         }
11325         else
11326         {
11327                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11328                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11329         }
11330         CHECKGLERROR
11331 }
11332
11333 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11334 {
11335         int i, j;
11336         texture_t *texture;
11337         R_FrameData_SetMark();
11338         // break the surface list down into batches by texture and use of lightmapping
11339         for (i = 0;i < numsurfaces;i = j)
11340         {
11341                 j = i + 1;
11342                 // texture is the base texture pointer, rsurface.texture is the
11343                 // current frame/skin the texture is directing us to use (for example
11344                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11345                 // use skin 1 instead)
11346                 texture = surfacelist[i]->texture;
11347                 rsurface.texture = R_GetCurrentTexture(texture);
11348                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11349                 {
11350                         // if this texture is not the kind we want, skip ahead to the next one
11351                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11352                                 ;
11353                         continue;
11354                 }
11355                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11356                 {
11357                         rsurface.lightmaptexture = NULL;
11358                         rsurface.deluxemaptexture = NULL;
11359                         rsurface.uselightmaptexture = false;
11360                         // simply scan ahead until we find a different texture or lightmap state
11361                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11362                                 ;
11363                 }
11364                 else
11365                 {
11366                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11367                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11368                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11369                         // simply scan ahead until we find a different texture or lightmap state
11370                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11371                                 ;
11372                 }
11373                 // render the range of surfaces
11374                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11375         }
11376         R_FrameData_ReturnToMark();
11377 }
11378
11379 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11380 {
11381         CHECKGLERROR
11382         if (depthonly)
11383                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11384         else if (prepass)
11385         {
11386                 if (!rsurface.texture->currentnumlayers)
11387                         return;
11388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11389                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11390                 else
11391                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11392         }
11393         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11394                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11395         else if (!rsurface.texture->currentnumlayers)
11396                 return;
11397         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11398         {
11399                 // in the deferred case, transparent surfaces were queued during prepass
11400                 if (!r_shadow_usingdeferredprepass)
11401                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11402         }
11403         else
11404         {
11405                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11406                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11407         }
11408         CHECKGLERROR
11409 }
11410
11411 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11412 {
11413         int i, j;
11414         texture_t *texture;
11415         R_FrameData_SetMark();
11416         // break the surface list down into batches by texture and use of lightmapping
11417         for (i = 0;i < numsurfaces;i = j)
11418         {
11419                 j = i + 1;
11420                 // texture is the base texture pointer, rsurface.texture is the
11421                 // current frame/skin the texture is directing us to use (for example
11422                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11423                 // use skin 1 instead)
11424                 texture = surfacelist[i]->texture;
11425                 rsurface.texture = R_GetCurrentTexture(texture);
11426                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11427                 {
11428                         // if this texture is not the kind we want, skip ahead to the next one
11429                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11430                                 ;
11431                         continue;
11432                 }
11433                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11434                 {
11435                         rsurface.lightmaptexture = NULL;
11436                         rsurface.deluxemaptexture = NULL;
11437                         rsurface.uselightmaptexture = false;
11438                         // simply scan ahead until we find a different texture or lightmap state
11439                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11440                                 ;
11441                 }
11442                 else
11443                 {
11444                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11445                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11446                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11447                         // simply scan ahead until we find a different texture or lightmap state
11448                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11449                                 ;
11450                 }
11451                 // render the range of surfaces
11452                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11453         }
11454         R_FrameData_ReturnToMark();
11455 }
11456
11457 float locboxvertex3f[6*4*3] =
11458 {
11459         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11460         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11461         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11462         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11463         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11464         1,0,0, 0,0,0, 0,1,0, 1,1,0
11465 };
11466
11467 unsigned short locboxelements[6*2*3] =
11468 {
11469          0, 1, 2, 0, 2, 3,
11470          4, 5, 6, 4, 6, 7,
11471          8, 9,10, 8,10,11,
11472         12,13,14, 12,14,15,
11473         16,17,18, 16,18,19,
11474         20,21,22, 20,22,23
11475 };
11476
11477 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11478 {
11479         int i, j;
11480         cl_locnode_t *loc = (cl_locnode_t *)ent;
11481         vec3_t mins, size;
11482         float vertex3f[6*4*3];
11483         CHECKGLERROR
11484         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11485         GL_DepthMask(false);
11486         GL_DepthRange(0, 1);
11487         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11488         GL_DepthTest(true);
11489         GL_CullFace(GL_NONE);
11490         R_EntityMatrix(&identitymatrix);
11491
11492 //      R_Mesh_ResetTextureState();
11493
11494         i = surfacelist[0];
11495         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11496                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11497                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11498                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11499
11500         if (VectorCompare(loc->mins, loc->maxs))
11501         {
11502                 VectorSet(size, 2, 2, 2);
11503                 VectorMA(loc->mins, -0.5f, size, mins);
11504         }
11505         else
11506         {
11507                 VectorCopy(loc->mins, mins);
11508                 VectorSubtract(loc->maxs, loc->mins, size);
11509         }
11510
11511         for (i = 0;i < 6*4*3;)
11512                 for (j = 0;j < 3;j++, i++)
11513                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11514
11515         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11516         R_SetupShader_Generic_NoTexture(false, false);
11517         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11518 }
11519
11520 void R_DrawLocs(void)
11521 {
11522         int index;
11523         cl_locnode_t *loc, *nearestloc;
11524         vec3_t center;
11525         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11526         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11527         {
11528                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11529                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11530         }
11531 }
11532
11533 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11534 {
11535         if (decalsystem->decals)
11536                 Mem_Free(decalsystem->decals);
11537         memset(decalsystem, 0, sizeof(*decalsystem));
11538 }
11539
11540 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)
11541 {
11542         tridecal_t *decal;
11543         tridecal_t *decals;
11544         int i;
11545
11546         // expand or initialize the system
11547         if (decalsystem->maxdecals <= decalsystem->numdecals)
11548         {
11549                 decalsystem_t old = *decalsystem;
11550                 qboolean useshortelements;
11551                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11552                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11553                 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)));
11554                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11555                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11556                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11557                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11558                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11559                 if (decalsystem->numdecals)
11560                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11561                 if (old.decals)
11562                         Mem_Free(old.decals);
11563                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11564                         decalsystem->element3i[i] = i;
11565                 if (useshortelements)
11566                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11567                                 decalsystem->element3s[i] = i;
11568         }
11569
11570         // grab a decal and search for another free slot for the next one
11571         decals = decalsystem->decals;
11572         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11573         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11574                 ;
11575         decalsystem->freedecal = i;
11576         if (decalsystem->numdecals <= i)
11577                 decalsystem->numdecals = i + 1;
11578
11579         // initialize the decal
11580         decal->lived = 0;
11581         decal->triangleindex = triangleindex;
11582         decal->surfaceindex = surfaceindex;
11583         decal->decalsequence = decalsequence;
11584         decal->color4f[0][0] = c0[0];
11585         decal->color4f[0][1] = c0[1];
11586         decal->color4f[0][2] = c0[2];
11587         decal->color4f[0][3] = 1;
11588         decal->color4f[1][0] = c1[0];
11589         decal->color4f[1][1] = c1[1];
11590         decal->color4f[1][2] = c1[2];
11591         decal->color4f[1][3] = 1;
11592         decal->color4f[2][0] = c2[0];
11593         decal->color4f[2][1] = c2[1];
11594         decal->color4f[2][2] = c2[2];
11595         decal->color4f[2][3] = 1;
11596         decal->vertex3f[0][0] = v0[0];
11597         decal->vertex3f[0][1] = v0[1];
11598         decal->vertex3f[0][2] = v0[2];
11599         decal->vertex3f[1][0] = v1[0];
11600         decal->vertex3f[1][1] = v1[1];
11601         decal->vertex3f[1][2] = v1[2];
11602         decal->vertex3f[2][0] = v2[0];
11603         decal->vertex3f[2][1] = v2[1];
11604         decal->vertex3f[2][2] = v2[2];
11605         decal->texcoord2f[0][0] = t0[0];
11606         decal->texcoord2f[0][1] = t0[1];
11607         decal->texcoord2f[1][0] = t1[0];
11608         decal->texcoord2f[1][1] = t1[1];
11609         decal->texcoord2f[2][0] = t2[0];
11610         decal->texcoord2f[2][1] = t2[1];
11611         TriangleNormal(v0, v1, v2, decal->plane);
11612         VectorNormalize(decal->plane);
11613         decal->plane[3] = DotProduct(v0, decal->plane);
11614 }
11615
11616 extern cvar_t cl_decals_bias;
11617 extern cvar_t cl_decals_models;
11618 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11619 // baseparms, parms, temps
11620 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)
11621 {
11622         int cornerindex;
11623         int index;
11624         float v[9][3];
11625         const float *vertex3f;
11626         const float *normal3f;
11627         int numpoints;
11628         float points[2][9][3];
11629         float temp[3];
11630         float tc[9][2];
11631         float f;
11632         float c[9][4];
11633         const int *e;
11634
11635         e = rsurface.modelelement3i + 3*triangleindex;
11636
11637         vertex3f = rsurface.modelvertex3f;
11638         normal3f = rsurface.modelnormal3f;
11639
11640         if (normal3f)
11641         {
11642                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11643                 {
11644                         index = 3*e[cornerindex];
11645                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11646                 }
11647         }
11648         else
11649         {
11650                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11651                 {
11652                         index = 3*e[cornerindex];
11653                         VectorCopy(vertex3f + index, v[cornerindex]);
11654                 }
11655         }
11656
11657         // cull backfaces
11658         //TriangleNormal(v[0], v[1], v[2], normal);
11659         //if (DotProduct(normal, localnormal) < 0.0f)
11660         //      continue;
11661         // clip by each of the box planes formed from the projection matrix
11662         // if anything survives, we emit the decal
11663         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]);
11664         if (numpoints < 3)
11665                 return;
11666         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]);
11667         if (numpoints < 3)
11668                 return;
11669         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]);
11670         if (numpoints < 3)
11671                 return;
11672         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]);
11673         if (numpoints < 3)
11674                 return;
11675         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]);
11676         if (numpoints < 3)
11677                 return;
11678         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]);
11679         if (numpoints < 3)
11680                 return;
11681         // some part of the triangle survived, so we have to accept it...
11682         if (dynamic)
11683         {
11684                 // dynamic always uses the original triangle
11685                 numpoints = 3;
11686                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11687                 {
11688                         index = 3*e[cornerindex];
11689                         VectorCopy(vertex3f + index, v[cornerindex]);
11690                 }
11691         }
11692         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11693         {
11694                 // convert vertex positions to texcoords
11695                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11696                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11697                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11698                 // calculate distance fade from the projection origin
11699                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11700                 f = bound(0.0f, f, 1.0f);
11701                 c[cornerindex][0] = r * f;
11702                 c[cornerindex][1] = g * f;
11703                 c[cornerindex][2] = b * f;
11704                 c[cornerindex][3] = 1.0f;
11705                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11706         }
11707         if (dynamic)
11708                 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);
11709         else
11710                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11711                         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);
11712 }
11713 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)
11714 {
11715         matrix4x4_t projection;
11716         decalsystem_t *decalsystem;
11717         qboolean dynamic;
11718         dp_model_t *model;
11719         const msurface_t *surface;
11720         const msurface_t *surfaces;
11721         const int *surfacelist;
11722         const texture_t *texture;
11723         int numtriangles;
11724         int numsurfacelist;
11725         int surfacelistindex;
11726         int surfaceindex;
11727         int triangleindex;
11728         float localorigin[3];
11729         float localnormal[3];
11730         float localmins[3];
11731         float localmaxs[3];
11732         float localsize;
11733         //float normal[3];
11734         float planes[6][4];
11735         float angles[3];
11736         bih_t *bih;
11737         int bih_triangles_count;
11738         int bih_triangles[256];
11739         int bih_surfaces[256];
11740
11741         decalsystem = &ent->decalsystem;
11742         model = ent->model;
11743         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11744         {
11745                 R_DecalSystem_Reset(&ent->decalsystem);
11746                 return;
11747         }
11748
11749         if (!model->brush.data_leafs && !cl_decals_models.integer)
11750         {
11751                 if (decalsystem->model)
11752                         R_DecalSystem_Reset(decalsystem);
11753                 return;
11754         }
11755
11756         if (decalsystem->model != model)
11757                 R_DecalSystem_Reset(decalsystem);
11758         decalsystem->model = model;
11759
11760         RSurf_ActiveModelEntity(ent, true, false, false);
11761
11762         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11763         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11764         VectorNormalize(localnormal);
11765         localsize = worldsize*rsurface.inversematrixscale;
11766         localmins[0] = localorigin[0] - localsize;
11767         localmins[1] = localorigin[1] - localsize;
11768         localmins[2] = localorigin[2] - localsize;
11769         localmaxs[0] = localorigin[0] + localsize;
11770         localmaxs[1] = localorigin[1] + localsize;
11771         localmaxs[2] = localorigin[2] + localsize;
11772
11773         //VectorCopy(localnormal, planes[4]);
11774         //VectorVectors(planes[4], planes[2], planes[0]);
11775         AnglesFromVectors(angles, localnormal, NULL, false);
11776         AngleVectors(angles, planes[0], planes[2], planes[4]);
11777         VectorNegate(planes[0], planes[1]);
11778         VectorNegate(planes[2], planes[3]);
11779         VectorNegate(planes[4], planes[5]);
11780         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11781         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11782         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11783         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11784         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11785         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11786
11787 #if 1
11788 // works
11789 {
11790         matrix4x4_t forwardprojection;
11791         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11792         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11793 }
11794 #else
11795 // broken
11796 {
11797         float projectionvector[4][3];
11798         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11799         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11800         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11801         projectionvector[0][0] = planes[0][0] * ilocalsize;
11802         projectionvector[0][1] = planes[1][0] * ilocalsize;
11803         projectionvector[0][2] = planes[2][0] * ilocalsize;
11804         projectionvector[1][0] = planes[0][1] * ilocalsize;
11805         projectionvector[1][1] = planes[1][1] * ilocalsize;
11806         projectionvector[1][2] = planes[2][1] * ilocalsize;
11807         projectionvector[2][0] = planes[0][2] * ilocalsize;
11808         projectionvector[2][1] = planes[1][2] * ilocalsize;
11809         projectionvector[2][2] = planes[2][2] * ilocalsize;
11810         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11811         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11812         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11813         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11814 }
11815 #endif
11816
11817         dynamic = model->surfmesh.isanimated;
11818         numsurfacelist = model->nummodelsurfaces;
11819         surfacelist = model->sortedmodelsurfaces;
11820         surfaces = model->data_surfaces;
11821
11822         bih = NULL;
11823         bih_triangles_count = -1;
11824         if(!dynamic)
11825         {
11826                 if(model->render_bih.numleafs)
11827                         bih = &model->render_bih;
11828                 else if(model->collision_bih.numleafs)
11829                         bih = &model->collision_bih;
11830         }
11831         if(bih)
11832                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11833         if(bih_triangles_count == 0)
11834                 return;
11835         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11836                 return;
11837         if(bih_triangles_count > 0)
11838         {
11839                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11840                 {
11841                         surfaceindex = bih_surfaces[triangleindex];
11842                         surface = surfaces + surfaceindex;
11843                         texture = surface->texture;
11844                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11845                                 continue;
11846                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11847                                 continue;
11848                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11849                 }
11850         }
11851         else
11852         {
11853                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11854                 {
11855                         surfaceindex = surfacelist[surfacelistindex];
11856                         surface = surfaces + surfaceindex;
11857                         // check cull box first because it rejects more than any other check
11858                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11859                                 continue;
11860                         // skip transparent surfaces
11861                         texture = surface->texture;
11862                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11863                                 continue;
11864                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11865                                 continue;
11866                         numtriangles = surface->num_triangles;
11867                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11868                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11869                 }
11870         }
11871 }
11872
11873 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11874 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)
11875 {
11876         int renderentityindex;
11877         float worldmins[3];
11878         float worldmaxs[3];
11879         entity_render_t *ent;
11880
11881         if (!cl_decals_newsystem.integer)
11882                 return;
11883
11884         worldmins[0] = worldorigin[0] - worldsize;
11885         worldmins[1] = worldorigin[1] - worldsize;
11886         worldmins[2] = worldorigin[2] - worldsize;
11887         worldmaxs[0] = worldorigin[0] + worldsize;
11888         worldmaxs[1] = worldorigin[1] + worldsize;
11889         worldmaxs[2] = worldorigin[2] + worldsize;
11890
11891         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11892
11893         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11894         {
11895                 ent = r_refdef.scene.entities[renderentityindex];
11896                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11897                         continue;
11898
11899                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11900         }
11901 }
11902
11903 typedef struct r_decalsystem_splatqueue_s
11904 {
11905         vec3_t worldorigin;
11906         vec3_t worldnormal;
11907         float color[4];
11908         float tcrange[4];
11909         float worldsize;
11910         int decalsequence;
11911 }
11912 r_decalsystem_splatqueue_t;
11913
11914 int r_decalsystem_numqueued = 0;
11915 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11916
11917 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)
11918 {
11919         r_decalsystem_splatqueue_t *queue;
11920
11921         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11922                 return;
11923
11924         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11925         VectorCopy(worldorigin, queue->worldorigin);
11926         VectorCopy(worldnormal, queue->worldnormal);
11927         Vector4Set(queue->color, r, g, b, a);
11928         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11929         queue->worldsize = worldsize;
11930         queue->decalsequence = cl.decalsequence++;
11931 }
11932
11933 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11934 {
11935         int i;
11936         r_decalsystem_splatqueue_t *queue;
11937
11938         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11939                 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);
11940         r_decalsystem_numqueued = 0;
11941 }
11942
11943 extern cvar_t cl_decals_max;
11944 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11945 {
11946         int i;
11947         decalsystem_t *decalsystem = &ent->decalsystem;
11948         int numdecals;
11949         int killsequence;
11950         tridecal_t *decal;
11951         float frametime;
11952         float lifetime;
11953
11954         if (!decalsystem->numdecals)
11955                 return;
11956
11957         if (r_showsurfaces.integer)
11958                 return;
11959
11960         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11961         {
11962                 R_DecalSystem_Reset(decalsystem);
11963                 return;
11964         }
11965
11966         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11967         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11968
11969         if (decalsystem->lastupdatetime)
11970                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11971         else
11972                 frametime = 0;
11973         decalsystem->lastupdatetime = r_refdef.scene.time;
11974         numdecals = decalsystem->numdecals;
11975
11976         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11977         {
11978                 if (decal->color4f[0][3])
11979                 {
11980                         decal->lived += frametime;
11981                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11982                         {
11983                                 memset(decal, 0, sizeof(*decal));
11984                                 if (decalsystem->freedecal > i)
11985                                         decalsystem->freedecal = i;
11986                         }
11987                 }
11988         }
11989         decal = decalsystem->decals;
11990         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11991                 numdecals--;
11992
11993         // collapse the array by shuffling the tail decals into the gaps
11994         for (;;)
11995         {
11996                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11997                         decalsystem->freedecal++;
11998                 if (decalsystem->freedecal == numdecals)
11999                         break;
12000                 decal[decalsystem->freedecal] = decal[--numdecals];
12001         }
12002
12003         decalsystem->numdecals = numdecals;
12004
12005         if (numdecals <= 0)
12006         {
12007                 // if there are no decals left, reset decalsystem
12008                 R_DecalSystem_Reset(decalsystem);
12009         }
12010 }
12011
12012 extern skinframe_t *decalskinframe;
12013 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12014 {
12015         int i;
12016         decalsystem_t *decalsystem = &ent->decalsystem;
12017         int numdecals;
12018         tridecal_t *decal;
12019         float faderate;
12020         float alpha;
12021         float *v3f;
12022         float *c4f;
12023         float *t2f;
12024         const int *e;
12025         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12026         int numtris = 0;
12027
12028         numdecals = decalsystem->numdecals;
12029         if (!numdecals)
12030                 return;
12031
12032         if (r_showsurfaces.integer)
12033                 return;
12034
12035         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12036         {
12037                 R_DecalSystem_Reset(decalsystem);
12038                 return;
12039         }
12040
12041         // if the model is static it doesn't matter what value we give for
12042         // wantnormals and wanttangents, so this logic uses only rules applicable
12043         // to a model, knowing that they are meaningless otherwise
12044         if (ent == r_refdef.scene.worldentity)
12045                 RSurf_ActiveWorldEntity();
12046         else
12047                 RSurf_ActiveModelEntity(ent, false, false, false);
12048
12049         decalsystem->lastupdatetime = r_refdef.scene.time;
12050
12051         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12052
12053         // update vertex positions for animated models
12054         v3f = decalsystem->vertex3f;
12055         c4f = decalsystem->color4f;
12056         t2f = decalsystem->texcoord2f;
12057         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12058         {
12059                 if (!decal->color4f[0][3])
12060                         continue;
12061
12062                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12063                         continue;
12064
12065                 // skip backfaces
12066                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12067                         continue;
12068
12069                 // update color values for fading decals
12070                 if (decal->lived >= cl_decals_time.value)
12071                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12072                 else
12073                         alpha = 1.0f;
12074
12075                 c4f[ 0] = decal->color4f[0][0] * alpha;
12076                 c4f[ 1] = decal->color4f[0][1] * alpha;
12077                 c4f[ 2] = decal->color4f[0][2] * alpha;
12078                 c4f[ 3] = 1;
12079                 c4f[ 4] = decal->color4f[1][0] * alpha;
12080                 c4f[ 5] = decal->color4f[1][1] * alpha;
12081                 c4f[ 6] = decal->color4f[1][2] * alpha;
12082                 c4f[ 7] = 1;
12083                 c4f[ 8] = decal->color4f[2][0] * alpha;
12084                 c4f[ 9] = decal->color4f[2][1] * alpha;
12085                 c4f[10] = decal->color4f[2][2] * alpha;
12086                 c4f[11] = 1;
12087
12088                 t2f[0] = decal->texcoord2f[0][0];
12089                 t2f[1] = decal->texcoord2f[0][1];
12090                 t2f[2] = decal->texcoord2f[1][0];
12091                 t2f[3] = decal->texcoord2f[1][1];
12092                 t2f[4] = decal->texcoord2f[2][0];
12093                 t2f[5] = decal->texcoord2f[2][1];
12094
12095                 // update vertex positions for animated models
12096                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12097                 {
12098                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12099                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12100                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12101                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12102                 }
12103                 else
12104                 {
12105                         VectorCopy(decal->vertex3f[0], v3f);
12106                         VectorCopy(decal->vertex3f[1], v3f + 3);
12107                         VectorCopy(decal->vertex3f[2], v3f + 6);
12108                 }
12109
12110                 if (r_refdef.fogenabled)
12111                 {
12112                         alpha = RSurf_FogVertex(v3f);
12113                         VectorScale(c4f, alpha, c4f);
12114                         alpha = RSurf_FogVertex(v3f + 3);
12115                         VectorScale(c4f + 4, alpha, c4f + 4);
12116                         alpha = RSurf_FogVertex(v3f + 6);
12117                         VectorScale(c4f + 8, alpha, c4f + 8);
12118                 }
12119
12120                 v3f += 9;
12121                 c4f += 12;
12122                 t2f += 6;
12123                 numtris++;
12124         }
12125
12126         if (numtris > 0)
12127         {
12128                 r_refdef.stats[r_stat_drawndecals] += numtris;
12129
12130                 // now render the decals all at once
12131                 // (this assumes they all use one particle font texture!)
12132                 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);
12133 //              R_Mesh_ResetTextureState();
12134                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12135                 GL_DepthMask(false);
12136                 GL_DepthRange(0, 1);
12137                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12138                 GL_DepthTest(true);
12139                 GL_CullFace(GL_NONE);
12140                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12141                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12142                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12143         }
12144 }
12145
12146 static void R_DrawModelDecals(void)
12147 {
12148         int i, numdecals;
12149
12150         // fade faster when there are too many decals
12151         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12152         for (i = 0;i < r_refdef.scene.numentities;i++)
12153                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12154
12155         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12156         for (i = 0;i < r_refdef.scene.numentities;i++)
12157                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12158                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12159
12160         R_DecalSystem_ApplySplatEntitiesQueue();
12161
12162         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12163         for (i = 0;i < r_refdef.scene.numentities;i++)
12164                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12165
12166         r_refdef.stats[r_stat_totaldecals] += numdecals;
12167
12168         if (r_showsurfaces.integer)
12169                 return;
12170
12171         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12172
12173         for (i = 0;i < r_refdef.scene.numentities;i++)
12174         {
12175                 if (!r_refdef.viewcache.entityvisible[i])
12176                         continue;
12177                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12178                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12179         }
12180 }
12181
12182 extern cvar_t mod_collision_bih;
12183 static void R_DrawDebugModel(void)
12184 {
12185         entity_render_t *ent = rsurface.entity;
12186         int i, j, k, l, flagsmask;
12187         const msurface_t *surface;
12188         dp_model_t *model = ent->model;
12189         vec3_t v;
12190
12191         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12192                 return;
12193
12194         if (r_showoverdraw.value > 0)
12195         {
12196                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12197                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12198                 R_SetupShader_Generic_NoTexture(false, false);
12199                 GL_DepthTest(false);
12200                 GL_DepthMask(false);
12201                 GL_DepthRange(0, 1);
12202                 GL_BlendFunc(GL_ONE, GL_ONE);
12203                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12204                 {
12205                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12206                                 continue;
12207                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12208                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12209                         {
12210                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12211                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12212                                 if (!rsurface.texture->currentlayers->depthmask)
12213                                         GL_Color(c, 0, 0, 1.0f);
12214                                 else if (ent == r_refdef.scene.worldentity)
12215                                         GL_Color(c, c, c, 1.0f);
12216                                 else
12217                                         GL_Color(0, c, 0, 1.0f);
12218                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12219                                 RSurf_DrawBatch();
12220                         }
12221                 }
12222                 rsurface.texture = NULL;
12223         }
12224
12225         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12226
12227 //      R_Mesh_ResetTextureState();
12228         R_SetupShader_Generic_NoTexture(false, false);
12229         GL_DepthRange(0, 1);
12230         GL_DepthTest(!r_showdisabledepthtest.integer);
12231         GL_DepthMask(false);
12232         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12233
12234         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12235         {
12236                 int triangleindex;
12237                 int bihleafindex;
12238                 qboolean cullbox = false;
12239                 const q3mbrush_t *brush;
12240                 const bih_t *bih = &model->collision_bih;
12241                 const bih_leaf_t *bihleaf;
12242                 float vertex3f[3][3];
12243                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12244                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12245                 {
12246                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12247                                 continue;
12248                         switch (bihleaf->type)
12249                         {
12250                         case BIH_BRUSH:
12251                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12252                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12253                                 {
12254                                         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);
12255                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12256                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12257                                 }
12258                                 break;
12259                         case BIH_COLLISIONTRIANGLE:
12260                                 triangleindex = bihleaf->itemindex;
12261                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12262                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12263                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12264                                 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);
12265                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12266                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12267                                 break;
12268                         case BIH_RENDERTRIANGLE:
12269                                 triangleindex = bihleaf->itemindex;
12270                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12271                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12272                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12273                                 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);
12274                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12275                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12276                                 break;
12277                         }
12278                 }
12279         }
12280
12281         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12282
12283 #ifndef USE_GLES2
12284         if (r_showtris.integer && qglPolygonMode)
12285         {
12286                 if (r_showdisabledepthtest.integer)
12287                 {
12288                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12289                         GL_DepthMask(false);
12290                 }
12291                 else
12292                 {
12293                         GL_BlendFunc(GL_ONE, GL_ZERO);
12294                         GL_DepthMask(true);
12295                 }
12296                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12297                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12298                 {
12299                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12300                                 continue;
12301                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12302                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12303                         {
12304                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12305                                 if (!rsurface.texture->currentlayers->depthmask)
12306                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12307                                 else if (ent == r_refdef.scene.worldentity)
12308                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12309                                 else
12310                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12311                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12312                                 RSurf_DrawBatch();
12313                         }
12314                 }
12315                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12316                 rsurface.texture = NULL;
12317         }
12318
12319         if (r_shownormals.value != 0 && qglBegin)
12320         {
12321                 if (r_showdisabledepthtest.integer)
12322                 {
12323                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12324                         GL_DepthMask(false);
12325                 }
12326                 else
12327                 {
12328                         GL_BlendFunc(GL_ONE, GL_ZERO);
12329                         GL_DepthMask(true);
12330                 }
12331                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12332                 {
12333                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12334                                 continue;
12335                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12336                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12337                         {
12338                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12339                                 qglBegin(GL_LINES);
12340                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12341                                 {
12342                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12343                                         {
12344                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12345                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12346                                                 qglVertex3f(v[0], v[1], v[2]);
12347                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12348                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12349                                                 qglVertex3f(v[0], v[1], v[2]);
12350                                         }
12351                                 }
12352                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12353                                 {
12354                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12355                                         {
12356                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12357                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12358                                                 qglVertex3f(v[0], v[1], v[2]);
12359                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12360                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12361                                                 qglVertex3f(v[0], v[1], v[2]);
12362                                         }
12363                                 }
12364                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12365                                 {
12366                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12367                                         {
12368                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12369                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12370                                                 qglVertex3f(v[0], v[1], v[2]);
12371                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12372                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12373                                                 qglVertex3f(v[0], v[1], v[2]);
12374                                         }
12375                                 }
12376                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12377                                 {
12378                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12379                                         {
12380                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12381                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12382                                                 qglVertex3f(v[0], v[1], v[2]);
12383                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12384                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12385                                                 qglVertex3f(v[0], v[1], v[2]);
12386                                         }
12387                                 }
12388                                 qglEnd();
12389                                 CHECKGLERROR
12390                         }
12391                 }
12392                 rsurface.texture = NULL;
12393         }
12394 #endif
12395 }
12396
12397 int r_maxsurfacelist = 0;
12398 const msurface_t **r_surfacelist = NULL;
12399 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12400 {
12401         int i, j, endj, flagsmask;
12402         dp_model_t *model = r_refdef.scene.worldmodel;
12403         msurface_t *surfaces;
12404         unsigned char *update;
12405         int numsurfacelist = 0;
12406         if (model == NULL)
12407                 return;
12408
12409         if (r_maxsurfacelist < model->num_surfaces)
12410         {
12411                 r_maxsurfacelist = model->num_surfaces;
12412                 if (r_surfacelist)
12413                         Mem_Free((msurface_t**)r_surfacelist);
12414                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12415         }
12416
12417         RSurf_ActiveWorldEntity();
12418
12419         surfaces = model->data_surfaces;
12420         update = model->brushq1.lightmapupdateflags;
12421
12422         // update light styles on this submodel
12423         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12424         {
12425                 model_brush_lightstyleinfo_t *style;
12426                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12427                 {
12428                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12429                         {
12430                                 int *list = style->surfacelist;
12431                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12432                                 for (j = 0;j < style->numsurfaces;j++)
12433                                         update[list[j]] = true;
12434                         }
12435                 }
12436         }
12437
12438         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12439
12440         if (debug)
12441         {
12442                 R_DrawDebugModel();
12443                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12444                 return;
12445         }
12446
12447         rsurface.lightmaptexture = NULL;
12448         rsurface.deluxemaptexture = NULL;
12449         rsurface.uselightmaptexture = false;
12450         rsurface.texture = NULL;
12451         rsurface.rtlight = NULL;
12452         numsurfacelist = 0;
12453         // add visible surfaces to draw list
12454         for (i = 0;i < model->nummodelsurfaces;i++)
12455         {
12456                 j = model->sortedmodelsurfaces[i];
12457                 if (r_refdef.viewcache.world_surfacevisible[j])
12458                         r_surfacelist[numsurfacelist++] = surfaces + j;
12459         }
12460         // update lightmaps if needed
12461         if (model->brushq1.firstrender)
12462         {
12463                 model->brushq1.firstrender = false;
12464                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12465                         if (update[j])
12466                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12467         }
12468         else if (update)
12469         {
12470                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12471                         if (r_refdef.viewcache.world_surfacevisible[j])
12472                                 if (update[j])
12473                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12474         }
12475         // don't do anything if there were no surfaces
12476         if (!numsurfacelist)
12477         {
12478                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12479                 return;
12480         }
12481         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12482
12483         // add to stats if desired
12484         if (r_speeds.integer && !skysurfaces && !depthonly)
12485         {
12486                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12487                 for (j = 0;j < numsurfacelist;j++)
12488                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12489         }
12490
12491         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12492 }
12493
12494 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12495 {
12496         int i, j, endj, flagsmask;
12497         dp_model_t *model = ent->model;
12498         msurface_t *surfaces;
12499         unsigned char *update;
12500         int numsurfacelist = 0;
12501         if (model == NULL)
12502                 return;
12503
12504         if (r_maxsurfacelist < model->num_surfaces)
12505         {
12506                 r_maxsurfacelist = model->num_surfaces;
12507                 if (r_surfacelist)
12508                         Mem_Free((msurface_t **)r_surfacelist);
12509                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12510         }
12511
12512         // if the model is static it doesn't matter what value we give for
12513         // wantnormals and wanttangents, so this logic uses only rules applicable
12514         // to a model, knowing that they are meaningless otherwise
12515         if (ent == r_refdef.scene.worldentity)
12516                 RSurf_ActiveWorldEntity();
12517         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12518                 RSurf_ActiveModelEntity(ent, false, false, false);
12519         else if (prepass)
12520                 RSurf_ActiveModelEntity(ent, true, true, true);
12521         else if (depthonly)
12522         {
12523                 switch (vid.renderpath)
12524                 {
12525                 case RENDERPATH_GL20:
12526                 case RENDERPATH_D3D9:
12527                 case RENDERPATH_D3D10:
12528                 case RENDERPATH_D3D11:
12529                 case RENDERPATH_SOFT:
12530                 case RENDERPATH_GLES2:
12531                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12532                         break;
12533                 case RENDERPATH_GL11:
12534                 case RENDERPATH_GL13:
12535                 case RENDERPATH_GLES1:
12536                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12537                         break;
12538                 }
12539         }
12540         else
12541         {
12542                 switch (vid.renderpath)
12543                 {
12544                 case RENDERPATH_GL20:
12545                 case RENDERPATH_D3D9:
12546                 case RENDERPATH_D3D10:
12547                 case RENDERPATH_D3D11:
12548                 case RENDERPATH_SOFT:
12549                 case RENDERPATH_GLES2:
12550                         RSurf_ActiveModelEntity(ent, true, true, false);
12551                         break;
12552                 case RENDERPATH_GL11:
12553                 case RENDERPATH_GL13:
12554                 case RENDERPATH_GLES1:
12555                         RSurf_ActiveModelEntity(ent, true, false, false);
12556                         break;
12557                 }
12558         }
12559
12560         surfaces = model->data_surfaces;
12561         update = model->brushq1.lightmapupdateflags;
12562
12563         // update light styles
12564         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12565         {
12566                 model_brush_lightstyleinfo_t *style;
12567                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12568                 {
12569                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12570                         {
12571                                 int *list = style->surfacelist;
12572                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12573                                 for (j = 0;j < style->numsurfaces;j++)
12574                                         update[list[j]] = true;
12575                         }
12576                 }
12577         }
12578
12579         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12580
12581         if (debug)
12582         {
12583                 R_DrawDebugModel();
12584                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12585                 return;
12586         }
12587
12588         rsurface.lightmaptexture = NULL;
12589         rsurface.deluxemaptexture = NULL;
12590         rsurface.uselightmaptexture = false;
12591         rsurface.texture = NULL;
12592         rsurface.rtlight = NULL;
12593         numsurfacelist = 0;
12594         // add visible surfaces to draw list
12595         for (i = 0;i < model->nummodelsurfaces;i++)
12596                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12597         // don't do anything if there were no surfaces
12598         if (!numsurfacelist)
12599         {
12600                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12601                 return;
12602         }
12603         // update lightmaps if needed
12604         if (update)
12605         {
12606                 int updated = 0;
12607                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12608                 {
12609                         if (update[j])
12610                         {
12611                                 updated++;
12612                                 R_BuildLightMap(ent, surfaces + j);
12613                         }
12614                 }
12615         }
12616
12617         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12618
12619         // add to stats if desired
12620         if (r_speeds.integer && !skysurfaces && !depthonly)
12621         {
12622                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12623                 for (j = 0;j < numsurfacelist;j++)
12624                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12625         }
12626
12627         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12628 }
12629
12630 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12631 {
12632         static texture_t texture;
12633         static msurface_t surface;
12634         const msurface_t *surfacelist = &surface;
12635
12636         // fake enough texture and surface state to render this geometry
12637
12638         texture.update_lastrenderframe = -1; // regenerate this texture
12639         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12640         texture.currentskinframe = skinframe;
12641         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12642         texture.offsetmapping = OFFSETMAPPING_OFF;
12643         texture.offsetscale = 1;
12644         texture.specularscalemod = 1;
12645         texture.specularpowermod = 1;
12646         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12647         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12648         // JUST GREP FOR "specularscalemod = 1".
12649
12650         surface.texture = &texture;
12651         surface.num_triangles = numtriangles;
12652         surface.num_firsttriangle = firsttriangle;
12653         surface.num_vertices = numvertices;
12654         surface.num_firstvertex = firstvertex;
12655
12656         // now render it
12657         rsurface.texture = R_GetCurrentTexture(surface.texture);
12658         rsurface.lightmaptexture = NULL;
12659         rsurface.deluxemaptexture = NULL;
12660         rsurface.uselightmaptexture = false;
12661         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12662 }
12663
12664 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)
12665 {
12666         static msurface_t surface;
12667         const msurface_t *surfacelist = &surface;
12668
12669         // fake enough texture and surface state to render this geometry
12670         surface.texture = texture;
12671         surface.num_triangles = numtriangles;
12672         surface.num_firsttriangle = firsttriangle;
12673         surface.num_vertices = numvertices;
12674         surface.num_firstvertex = firstvertex;
12675
12676         // now render it
12677         rsurface.texture = R_GetCurrentTexture(surface.texture);
12678         rsurface.lightmaptexture = NULL;
12679         rsurface.deluxemaptexture = NULL;
12680         rsurface.uselightmaptexture = false;
12681         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12682 }