]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
don't call glGetUniformBlockIndex without GL_ARB_uniform_buffer_object
[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 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
234
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 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"};
237
238 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."};
239
240 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)"};
241 cvar_t r_bufferdatasize[R_BUFFERDATA_COUNT] =
242 {
243         {CVAR_SAVE, "r_bufferdatasize_vertex", "4", "vertex buffer size for one frame"},
244         {CVAR_SAVE, "r_bufferdatasize_index16", "1", "index buffer size for one frame (16bit indices)"},
245         {CVAR_SAVE, "r_bufferdatasize_index32", "1", "index buffer size for one frame (32bit indices)"},
246         {CVAR_SAVE, "r_bufferdatasize_uniform", "0.25", "uniform buffer size for one frame"},
247 };
248
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
251
252 extern qboolean v_flipped_state;
253
254 r_framebufferstate_t r_fb;
255
256 /// shadow volume bsp struct with automatically growing nodes buffer
257 svbsp_t r_svbsp;
258
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 255; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstrings[] =
617 {
618 #include "shader_glsl.h"
619 0
620 };
621
622 const char *builtinhlslshaderstrings[] =
623 {
624 #include "shader_hlsl.h"
625 0
626 };
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *filename;
643         const char *pretext;
644         const char *name;
645 }
646 shadermodeinfo_t;
647
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {
651         {"#define USEDIFFUSE\n", " diffuse"},
652         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653         {"#define USEVIEWTINT\n", " viewtint"},
654         {"#define USECOLORMAPPING\n", " colormapping"},
655         {"#define USESATURATION\n", " saturation"},
656         {"#define USEFOGINSIDE\n", " foginside"},
657         {"#define USEFOGOUTSIDE\n", " fogoutside"},
658         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660         {"#define USEGAMMARAMPS\n", " gammaramps"},
661         {"#define USECUBEFILTER\n", " cubefilter"},
662         {"#define USEGLOW\n", " glow"},
663         {"#define USEBLOOM\n", " bloom"},
664         {"#define USESPECULAR\n", " specular"},
665         {"#define USEPOSTPROCESSING\n", " postprocessing"},
666         {"#define USEREFLECTION\n", " reflection"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
671         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673         {"#define USEALPHAKILL\n", " alphakill"},
674         {"#define USEREFLECTCUBE\n", " reflectcube"},
675         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676         {"#define USEBOUNCEGRID\n", " bouncegrid"},
677         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
678         {"#define USETRIPPY\n", " trippy"},
679         {"#define USEDEPTHRGB\n", " depthrgb"},
680         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681         {"#define USESKELETAL\n", " skeletal"}
682 };
683
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {
687         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
702         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {
708         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725 };
726
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
729 {
730         /// hash lookup data
731         struct r_glsl_permutation_s *hashnext;
732         unsigned int mode;
733         unsigned int permutation;
734
735         /// indicates if we have tried compiling this permutation already
736         qboolean compiled;
737         /// 0 if compilation failed
738         int program;
739         // texture units assigned to each detected uniform
740         int tex_Texture_First;
741         int tex_Texture_Second;
742         int tex_Texture_GammaRamps;
743         int tex_Texture_Normal;
744         int tex_Texture_Color;
745         int tex_Texture_Gloss;
746         int tex_Texture_Glow;
747         int tex_Texture_SecondaryNormal;
748         int tex_Texture_SecondaryColor;
749         int tex_Texture_SecondaryGloss;
750         int tex_Texture_SecondaryGlow;
751         int tex_Texture_Pants;
752         int tex_Texture_Shirt;
753         int tex_Texture_FogHeightTexture;
754         int tex_Texture_FogMask;
755         int tex_Texture_Lightmap;
756         int tex_Texture_Deluxemap;
757         int tex_Texture_Attenuation;
758         int tex_Texture_Cube;
759         int tex_Texture_Refraction;
760         int tex_Texture_Reflection;
761         int tex_Texture_ShadowMap2D;
762         int tex_Texture_CubeProjection;
763         int tex_Texture_ScreenNormalMap;
764         int tex_Texture_ScreenDiffuse;
765         int tex_Texture_ScreenSpecular;
766         int tex_Texture_ReflectMask;
767         int tex_Texture_ReflectCube;
768         int tex_Texture_BounceGrid;
769         /// locations of detected uniforms in program object, or -1 if not found
770         int loc_Texture_First;
771         int loc_Texture_Second;
772         int loc_Texture_GammaRamps;
773         int loc_Texture_Normal;
774         int loc_Texture_Color;
775         int loc_Texture_Gloss;
776         int loc_Texture_Glow;
777         int loc_Texture_SecondaryNormal;
778         int loc_Texture_SecondaryColor;
779         int loc_Texture_SecondaryGloss;
780         int loc_Texture_SecondaryGlow;
781         int loc_Texture_Pants;
782         int loc_Texture_Shirt;
783         int loc_Texture_FogHeightTexture;
784         int loc_Texture_FogMask;
785         int loc_Texture_Lightmap;
786         int loc_Texture_Deluxemap;
787         int loc_Texture_Attenuation;
788         int loc_Texture_Cube;
789         int loc_Texture_Refraction;
790         int loc_Texture_Reflection;
791         int loc_Texture_ShadowMap2D;
792         int loc_Texture_CubeProjection;
793         int loc_Texture_ScreenNormalMap;
794         int loc_Texture_ScreenDiffuse;
795         int loc_Texture_ScreenSpecular;
796         int loc_Texture_ReflectMask;
797         int loc_Texture_ReflectCube;
798         int loc_Texture_BounceGrid;
799         int loc_Alpha;
800         int loc_BloomBlur_Parameters;
801         int loc_ClientTime;
802         int loc_Color_Ambient;
803         int loc_Color_Diffuse;
804         int loc_Color_Specular;
805         int loc_Color_Glow;
806         int loc_Color_Pants;
807         int loc_Color_Shirt;
808         int loc_DeferredColor_Ambient;
809         int loc_DeferredColor_Diffuse;
810         int loc_DeferredColor_Specular;
811         int loc_DeferredMod_Diffuse;
812         int loc_DeferredMod_Specular;
813         int loc_DistortScaleRefractReflect;
814         int loc_EyePosition;
815         int loc_FogColor;
816         int loc_FogHeightFade;
817         int loc_FogPlane;
818         int loc_FogPlaneViewDist;
819         int loc_FogRangeRecip;
820         int loc_LightColor;
821         int loc_LightDir;
822         int loc_LightPosition;
823         int loc_OffsetMapping_ScaleSteps;
824         int loc_OffsetMapping_LodDistance;
825         int loc_OffsetMapping_Bias;
826         int loc_PixelSize;
827         int loc_ReflectColor;
828         int loc_ReflectFactor;
829         int loc_ReflectOffset;
830         int loc_RefractColor;
831         int loc_Saturation;
832         int loc_ScreenCenterRefractReflect;
833         int loc_ScreenScaleRefractReflect;
834         int loc_ScreenToDepth;
835         int loc_ShadowMap_Parameters;
836         int loc_ShadowMap_TextureScale;
837         int loc_SpecularPower;
838         int loc_Skeletal_Transform12;
839         int loc_UserVec1;
840         int loc_UserVec2;
841         int loc_UserVec3;
842         int loc_UserVec4;
843         int loc_ViewTintColor;
844         int loc_ViewToLight;
845         int loc_ModelToLight;
846         int loc_TexMatrix;
847         int loc_BackgroundTexMatrix;
848         int loc_ModelViewProjectionMatrix;
849         int loc_ModelViewMatrix;
850         int loc_PixelToScreenTexCoord;
851         int loc_ModelToReflectCube;
852         int loc_ShadowMapMatrix;
853         int loc_BloomColorSubtract;
854         int loc_NormalmapScrollBlend;
855         int loc_BounceGridMatrix;
856         int loc_BounceGridIntensity;
857         /// uniform block bindings
858         int ubibind_Skeletal_Transform12_UniformBlock;
859         /// uniform block indices
860         int ubiloc_Skeletal_Transform12_UniformBlock;
861 }
862 r_glsl_permutation_t;
863
864 #define SHADERPERMUTATION_HASHSIZE 256
865
866
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
869 enum
870 {
871         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
877         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
879         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
880         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
881         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
882         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
883         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
884 };
885 #define SHADERSTATICPARMS_COUNT 13
886
887 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
888 static int shaderstaticparms_count = 0;
889
890 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
891 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
892
893 extern qboolean r_shadow_shadowmapsampler;
894 extern int r_shadow_shadowmappcf;
895 qboolean R_CompileShader_CheckStaticParms(void)
896 {
897         static int r_compileshader_staticparms_save[1];
898         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
899         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
900
901         // detect all
902         if (r_glsl_saturation_redcompensate.integer)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
904         if (r_glsl_vertextextureblend_usebothalphas.integer)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
906         if (r_shadow_glossexact.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
908         if (r_glsl_postprocess.integer)
909         {
910                 if (r_glsl_postprocess_uservec1_enable.integer)
911                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
912                 if (r_glsl_postprocess_uservec2_enable.integer)
913                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
914                 if (r_glsl_postprocess_uservec3_enable.integer)
915                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
916                 if (r_glsl_postprocess_uservec4_enable.integer)
917                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
918         }
919         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
920                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
921
922         if (r_shadow_shadowmapsampler)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
924         if (r_shadow_shadowmappcf > 1)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
926         else if (r_shadow_shadowmappcf)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
928         if (r_celshading.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
930         if (r_celoutlines.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
932
933         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
934 }
935
936 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
937         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
938                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
939         else \
940                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
941 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
942 {
943         shaderstaticparms_count = 0;
944
945         // emit all
946         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
947         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
948         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
949         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
950         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
951         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
952         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
953         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
954         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
955         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
956         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
957         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
958         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
959 }
960
961 /// information about each possible shader permutation
962 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
963 /// currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
965 /// storage for permutations linked in the hash table
966 memexpandablearray_t r_glsl_permutationarray;
967
968 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
969 {
970         //unsigned int hashdepth = 0;
971         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
972         r_glsl_permutation_t *p;
973         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
974         {
975                 if (p->mode == mode && p->permutation == permutation)
976                 {
977                         //if (hashdepth > 10)
978                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
979                         return p;
980                 }
981                 //hashdepth++;
982         }
983         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
984         p->mode = mode;
985         p->permutation = permutation;
986         p->hashnext = r_glsl_permutationhash[mode][hashindex];
987         r_glsl_permutationhash[mode][hashindex] = p;
988         //if (hashdepth > 10)
989         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
990         return p;
991 }
992
993 static char *R_ShaderStrCat(const char **strings)
994 {
995         char *string, *s;
996         const char **p = strings;
997         const char *t;
998         size_t len = 0;
999         for (p = strings;(t = *p);p++)
1000                 len += strlen(t);
1001         len++;
1002         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1003         len = 0;
1004         for (p = strings;(t = *p);p++)
1005         {
1006                 len = strlen(t);
1007                 memcpy(s, t, len);
1008                 s += len;
1009         }
1010         *s = 0;
1011         return string;
1012 }
1013
1014 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1015 {
1016         char *shaderstring;
1017         if (!filename || !filename[0])
1018                 return NULL;
1019         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1020         if (!strcmp(filename, "glsl/default.glsl"))
1021         {
1022                 if (builtinonly)
1023                         return R_ShaderStrCat(builtinshaderstrings);
1024                 if (!glslshaderstring)
1025                 {
1026                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1027                         if (glslshaderstring)
1028                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1029                         else
1030                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1031                 }
1032                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1033                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1034                 return shaderstring;
1035         }
1036         if (!strcmp(filename, "hlsl/default.hlsl"))
1037         {
1038                 if (builtinonly)
1039                         return R_ShaderStrCat(builtinhlslshaderstrings);
1040                 if (!hlslshaderstring)
1041                 {
1042                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1043                         if (hlslshaderstring)
1044                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1045                         else
1046                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1047                 }
1048                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1049                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1050                 return shaderstring;
1051         }
1052         // we don't have builtin strings for any other files
1053         if (builtinonly)
1054                 return NULL;
1055         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1056         if (shaderstring)
1057         {
1058                 if (printfromdisknotice)
1059                         Con_DPrintf("from disk %s... ", filename);
1060                 return shaderstring;
1061         }
1062         return shaderstring;
1063 }
1064
1065 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1066 {
1067         int i;
1068         int ubibind;
1069         int sampler;
1070         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1071         char *sourcestring;
1072         char permutationname[256];
1073         int vertstrings_count = 0;
1074         int geomstrings_count = 0;
1075         int fragstrings_count = 0;
1076         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1079
1080         if (p->compiled)
1081                 return;
1082         p->compiled = true;
1083         p->program = 0;
1084
1085         permutationname[0] = 0;
1086         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1087
1088         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1089
1090         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1091         if(vid.support.glshaderversion >= 140)
1092         {
1093                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1094                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1095                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1096                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1097                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1098                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1099         }
1100         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1101         else if(vid.support.glshaderversion >= 130)
1102         {
1103                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1104                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1105                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1106                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1107                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1108                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1109         }
1110
1111         // the first pretext is which type of shader to compile as
1112         // (later these will all be bound together as a program object)
1113         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1116
1117         // the second pretext is the mode (for example a light source)
1118         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1122
1123         // now add all the permutation pretexts
1124         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1125         {
1126                 if (permutation & (1<<i))
1127                 {
1128                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1132                 }
1133                 else
1134                 {
1135                         // keep line numbers correct
1136                         vertstrings_list[vertstrings_count++] = "\n";
1137                         geomstrings_list[geomstrings_count++] = "\n";
1138                         fragstrings_list[fragstrings_count++] = "\n";
1139                 }
1140         }
1141
1142         // add static parms
1143         R_CompileShader_AddStaticParms(mode, permutation);
1144         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145         vertstrings_count += shaderstaticparms_count;
1146         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147         geomstrings_count += shaderstaticparms_count;
1148         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149         fragstrings_count += shaderstaticparms_count;
1150
1151         // now append the shader text itself
1152         vertstrings_list[vertstrings_count++] = sourcestring;
1153         geomstrings_list[geomstrings_count++] = sourcestring;
1154         fragstrings_list[fragstrings_count++] = sourcestring;
1155
1156         // compile the shader program
1157         if (vertstrings_count + geomstrings_count + fragstrings_count)
1158                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1159         if (p->program)
1160         {
1161                 CHECKGLERROR
1162                 qglUseProgram(p->program);CHECKGLERROR
1163                 // look up all the uniform variable names we care about, so we don't
1164                 // have to look them up every time we set them
1165
1166                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1167                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1168                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1169                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1170                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1171                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1172                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1173                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1174                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1175                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1176                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1177                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1178                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1179                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1180                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1181                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1182                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1183                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1184                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1185                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1186                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1187                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1188                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1189                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1190                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1191                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1192                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1193                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1194                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1195                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1196                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1197                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1198                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1199                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1200                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1201                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1202                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1203                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1204                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1205                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1206                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1207                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1208                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1209                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1210                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1211                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1212                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1213                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1214                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1215                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1216                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1217                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1218                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1219                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1220                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1221                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1222                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1223                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1224                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1225                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1226                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1227                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1228                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1229                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1230                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1231                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1232                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1233                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1234                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1235                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1236                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1237                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1238                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1239                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1240                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1241                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1242                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1243                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1244                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1245                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1246                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1247                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1248                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1249                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1250                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1251                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1252                 // initialize the samplers to refer to the texture units we use
1253                 p->tex_Texture_First = -1;
1254                 p->tex_Texture_Second = -1;
1255                 p->tex_Texture_GammaRamps = -1;
1256                 p->tex_Texture_Normal = -1;
1257                 p->tex_Texture_Color = -1;
1258                 p->tex_Texture_Gloss = -1;
1259                 p->tex_Texture_Glow = -1;
1260                 p->tex_Texture_SecondaryNormal = -1;
1261                 p->tex_Texture_SecondaryColor = -1;
1262                 p->tex_Texture_SecondaryGloss = -1;
1263                 p->tex_Texture_SecondaryGlow = -1;
1264                 p->tex_Texture_Pants = -1;
1265                 p->tex_Texture_Shirt = -1;
1266                 p->tex_Texture_FogHeightTexture = -1;
1267                 p->tex_Texture_FogMask = -1;
1268                 p->tex_Texture_Lightmap = -1;
1269                 p->tex_Texture_Deluxemap = -1;
1270                 p->tex_Texture_Attenuation = -1;
1271                 p->tex_Texture_Cube = -1;
1272                 p->tex_Texture_Refraction = -1;
1273                 p->tex_Texture_Reflection = -1;
1274                 p->tex_Texture_ShadowMap2D = -1;
1275                 p->tex_Texture_CubeProjection = -1;
1276                 p->tex_Texture_ScreenNormalMap = -1;
1277                 p->tex_Texture_ScreenDiffuse = -1;
1278                 p->tex_Texture_ScreenSpecular = -1;
1279                 p->tex_Texture_ReflectMask = -1;
1280                 p->tex_Texture_ReflectCube = -1;
1281                 p->tex_Texture_BounceGrid = -1;
1282                 // bind the texture samplers in use
1283                 sampler = 0;
1284                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1285                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1286                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1287                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1288                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1289                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1290                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1291                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1292                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1293                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1294                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1295                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1296                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1297                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1298                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1299                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1300                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1301                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1302                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1303                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1304                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1305                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1306                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1307                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1308                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1309                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1310                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1311                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1312                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1313                 // get the uniform block indices so we can bind them
1314                 if (vid.support.arb_uniform_buffer_object)
1315                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1316                 else
1317                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1318                 // clear the uniform block bindings
1319                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1320                 // bind the uniform blocks in use
1321                 ubibind = 0;
1322                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1323                 // we're done compiling and setting up the shader, at least until it is used
1324                 CHECKGLERROR
1325                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1326         }
1327         else
1328                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1329
1330         // free the strings
1331         if (sourcestring)
1332                 Mem_Free(sourcestring);
1333 }
1334
1335 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1336 {
1337         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1338         if (r_glsl_permutation != perm)
1339         {
1340                 r_glsl_permutation = perm;
1341                 if (!r_glsl_permutation->program)
1342                 {
1343                         if (!r_glsl_permutation->compiled)
1344                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1345                         if (!r_glsl_permutation->program)
1346                         {
1347                                 // remove features until we find a valid permutation
1348                                 int i;
1349                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1350                                 {
1351                                         // reduce i more quickly whenever it would not remove any bits
1352                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1353                                         if (!(permutation & j))
1354                                                 continue;
1355                                         permutation -= j;
1356                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1357                                         if (!r_glsl_permutation->compiled)
1358                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1359                                         if (r_glsl_permutation->program)
1360                                                 break;
1361                                 }
1362                                 if (i >= SHADERPERMUTATION_COUNT)
1363                                 {
1364                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1365                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1366                                         qglUseProgram(0);CHECKGLERROR
1367                                         return; // no bit left to clear, entire mode is broken
1368                                 }
1369                         }
1370                 }
1371                 CHECKGLERROR
1372                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1373         }
1374         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1375         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1376         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1377 }
1378
1379 #ifdef SUPPORTD3D
1380
1381 #ifdef SUPPORTD3D
1382 #include <d3d9.h>
1383 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1384 extern D3DCAPS9 vid_d3d9caps;
1385 #endif
1386
1387 struct r_hlsl_permutation_s;
1388 typedef struct r_hlsl_permutation_s
1389 {
1390         /// hash lookup data
1391         struct r_hlsl_permutation_s *hashnext;
1392         unsigned int mode;
1393         unsigned int permutation;
1394
1395         /// indicates if we have tried compiling this permutation already
1396         qboolean compiled;
1397         /// NULL if compilation failed
1398         IDirect3DVertexShader9 *vertexshader;
1399         IDirect3DPixelShader9 *pixelshader;
1400 }
1401 r_hlsl_permutation_t;
1402
1403 typedef enum D3DVSREGISTER_e
1404 {
1405         D3DVSREGISTER_TexMatrix = 0, // float4x4
1406         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1407         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1408         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1409         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1410         D3DVSREGISTER_ModelToLight = 20, // float4x4
1411         D3DVSREGISTER_EyePosition = 24,
1412         D3DVSREGISTER_FogPlane = 25,
1413         D3DVSREGISTER_LightDir = 26,
1414         D3DVSREGISTER_LightPosition = 27,
1415 }
1416 D3DVSREGISTER_t;
1417
1418 typedef enum D3DPSREGISTER_e
1419 {
1420         D3DPSREGISTER_Alpha = 0,
1421         D3DPSREGISTER_BloomBlur_Parameters = 1,
1422         D3DPSREGISTER_ClientTime = 2,
1423         D3DPSREGISTER_Color_Ambient = 3,
1424         D3DPSREGISTER_Color_Diffuse = 4,
1425         D3DPSREGISTER_Color_Specular = 5,
1426         D3DPSREGISTER_Color_Glow = 6,
1427         D3DPSREGISTER_Color_Pants = 7,
1428         D3DPSREGISTER_Color_Shirt = 8,
1429         D3DPSREGISTER_DeferredColor_Ambient = 9,
1430         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1431         D3DPSREGISTER_DeferredColor_Specular = 11,
1432         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1433         D3DPSREGISTER_DeferredMod_Specular = 13,
1434         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1435         D3DPSREGISTER_EyePosition = 15, // unused
1436         D3DPSREGISTER_FogColor = 16,
1437         D3DPSREGISTER_FogHeightFade = 17,
1438         D3DPSREGISTER_FogPlane = 18,
1439         D3DPSREGISTER_FogPlaneViewDist = 19,
1440         D3DPSREGISTER_FogRangeRecip = 20,
1441         D3DPSREGISTER_LightColor = 21,
1442         D3DPSREGISTER_LightDir = 22, // unused
1443         D3DPSREGISTER_LightPosition = 23,
1444         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1445         D3DPSREGISTER_PixelSize = 25,
1446         D3DPSREGISTER_ReflectColor = 26,
1447         D3DPSREGISTER_ReflectFactor = 27,
1448         D3DPSREGISTER_ReflectOffset = 28,
1449         D3DPSREGISTER_RefractColor = 29,
1450         D3DPSREGISTER_Saturation = 30,
1451         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1452         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1453         D3DPSREGISTER_ScreenToDepth = 33,
1454         D3DPSREGISTER_ShadowMap_Parameters = 34,
1455         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1456         D3DPSREGISTER_SpecularPower = 36,
1457         D3DPSREGISTER_UserVec1 = 37,
1458         D3DPSREGISTER_UserVec2 = 38,
1459         D3DPSREGISTER_UserVec3 = 39,
1460         D3DPSREGISTER_UserVec4 = 40,
1461         D3DPSREGISTER_ViewTintColor = 41,
1462         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1463         D3DPSREGISTER_BloomColorSubtract = 43,
1464         D3DPSREGISTER_ViewToLight = 44, // float4x4
1465         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1466         D3DPSREGISTER_NormalmapScrollBlend = 52,
1467         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1468         D3DPSREGISTER_OffsetMapping_Bias = 54,
1469         // next at 54
1470 }
1471 D3DPSREGISTER_t;
1472
1473 /// information about each possible shader permutation
1474 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1475 /// currently selected permutation
1476 r_hlsl_permutation_t *r_hlsl_permutation;
1477 /// storage for permutations linked in the hash table
1478 memexpandablearray_t r_hlsl_permutationarray;
1479
1480 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1481 {
1482         //unsigned int hashdepth = 0;
1483         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1484         r_hlsl_permutation_t *p;
1485         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1486         {
1487                 if (p->mode == mode && p->permutation == permutation)
1488                 {
1489                         //if (hashdepth > 10)
1490                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1491                         return p;
1492                 }
1493                 //hashdepth++;
1494         }
1495         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1496         p->mode = mode;
1497         p->permutation = permutation;
1498         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1499         r_hlsl_permutationhash[mode][hashindex] = p;
1500         //if (hashdepth > 10)
1501         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1502         return p;
1503 }
1504
1505 #include <d3dx9.h>
1506 //#include <d3dx9shader.h>
1507 //#include <d3dx9mesh.h>
1508
1509 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1510 {
1511         DWORD *vsbin = NULL;
1512         DWORD *psbin = NULL;
1513         fs_offset_t vsbinsize;
1514         fs_offset_t psbinsize;
1515 //      IDirect3DVertexShader9 *vs = NULL;
1516 //      IDirect3DPixelShader9 *ps = NULL;
1517         ID3DXBuffer *vslog = NULL;
1518         ID3DXBuffer *vsbuffer = NULL;
1519         ID3DXConstantTable *vsconstanttable = NULL;
1520         ID3DXBuffer *pslog = NULL;
1521         ID3DXBuffer *psbuffer = NULL;
1522         ID3DXConstantTable *psconstanttable = NULL;
1523         int vsresult = 0;
1524         int psresult = 0;
1525         char temp[MAX_INPUTLINE];
1526         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1527         char vabuf[1024];
1528         qboolean debugshader = gl_paranoid.integer != 0;
1529         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1530         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1531         if (!debugshader)
1532         {
1533                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1534                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1535         }
1536         if ((!vsbin && vertstring) || (!psbin && fragstring))
1537         {
1538                 const char* dllnames_d3dx9 [] =
1539                 {
1540                         "d3dx9_43.dll",
1541                         "d3dx9_42.dll",
1542                         "d3dx9_41.dll",
1543                         "d3dx9_40.dll",
1544                         "d3dx9_39.dll",
1545                         "d3dx9_38.dll",
1546                         "d3dx9_37.dll",
1547                         "d3dx9_36.dll",
1548                         "d3dx9_35.dll",
1549                         "d3dx9_34.dll",
1550                         "d3dx9_33.dll",
1551                         "d3dx9_32.dll",
1552                         "d3dx9_31.dll",
1553                         "d3dx9_30.dll",
1554                         "d3dx9_29.dll",
1555                         "d3dx9_28.dll",
1556                         "d3dx9_27.dll",
1557                         "d3dx9_26.dll",
1558                         "d3dx9_25.dll",
1559                         "d3dx9_24.dll",
1560                         NULL
1561                 };
1562                 dllhandle_t d3dx9_dll = NULL;
1563                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1564                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1565                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1566                 dllfunction_t d3dx9_dllfuncs[] =
1567                 {
1568                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1569                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1570                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1571                         {NULL, NULL}
1572                 };
1573                 // 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...
1574 #ifndef ID3DXBuffer_GetBufferPointer
1575 #if !defined(__cplusplus) || defined(CINTERFACE)
1576 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1577 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1578 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1579 #else
1580 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1581 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1582 #define ID3DXBuffer_Release(p)            (p)->Release()
1583 #endif
1584 #endif
1585                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1586                 {
1587                         DWORD shaderflags = 0;
1588                         if (debugshader)
1589                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1590                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1591                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1592                         if (vertstring && vertstring[0])
1593                         {
1594                                 if (debugshader)
1595                                 {
1596                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1597                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1598                                 }
1599                                 else
1600                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1601                                 if (vsbuffer)
1602                                 {
1603                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1604                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1605                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1606                                         ID3DXBuffer_Release(vsbuffer);
1607                                 }
1608                                 if (vslog)
1609                                 {
1610                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1611                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1612                                         ID3DXBuffer_Release(vslog);
1613                                 }
1614                         }
1615                         if (fragstring && fragstring[0])
1616                         {
1617                                 if (debugshader)
1618                                 {
1619                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1620                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1621                                 }
1622                                 else
1623                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1624                                 if (psbuffer)
1625                                 {
1626                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1627                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1628                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1629                                         ID3DXBuffer_Release(psbuffer);
1630                                 }
1631                                 if (pslog)
1632                                 {
1633                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1634                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1635                                         ID3DXBuffer_Release(pslog);
1636                                 }
1637                         }
1638                         Sys_UnloadLibrary(&d3dx9_dll);
1639                 }
1640                 else
1641                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1642         }
1643         if (vsbin && psbin)
1644         {
1645                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1646                 if (FAILED(vsresult))
1647                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1648                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1649                 if (FAILED(psresult))
1650                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1651         }
1652         // free the shader data
1653         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1654         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1655 }
1656
1657 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1658 {
1659         int i;
1660         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1661         int vertstring_length = 0;
1662         int geomstring_length = 0;
1663         int fragstring_length = 0;
1664         char *t;
1665         char *sourcestring;
1666         char *vertstring, *geomstring, *fragstring;
1667         char permutationname[256];
1668         char cachename[256];
1669         int vertstrings_count = 0;
1670         int geomstrings_count = 0;
1671         int fragstrings_count = 0;
1672         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1673         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1674         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1675
1676         if (p->compiled)
1677                 return;
1678         p->compiled = true;
1679         p->vertexshader = NULL;
1680         p->pixelshader = NULL;
1681
1682         permutationname[0] = 0;
1683         cachename[0] = 0;
1684         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1685
1686         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1687         strlcat(cachename, "hlsl/", sizeof(cachename));
1688
1689         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1690         vertstrings_count = 0;
1691         geomstrings_count = 0;
1692         fragstrings_count = 0;
1693         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1694         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1695         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1696
1697         // the first pretext is which type of shader to compile as
1698         // (later these will all be bound together as a program object)
1699         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1700         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1701         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1702
1703         // the second pretext is the mode (for example a light source)
1704         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1705         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1706         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1707         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1708         strlcat(cachename, modeinfo->name, sizeof(cachename));
1709
1710         // now add all the permutation pretexts
1711         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1712         {
1713                 if (permutation & (1<<i))
1714                 {
1715                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1716                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1717                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1718                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1719                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1720                 }
1721                 else
1722                 {
1723                         // keep line numbers correct
1724                         vertstrings_list[vertstrings_count++] = "\n";
1725                         geomstrings_list[geomstrings_count++] = "\n";
1726                         fragstrings_list[fragstrings_count++] = "\n";
1727                 }
1728         }
1729
1730         // add static parms
1731         R_CompileShader_AddStaticParms(mode, permutation);
1732         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1733         vertstrings_count += shaderstaticparms_count;
1734         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1735         geomstrings_count += shaderstaticparms_count;
1736         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1737         fragstrings_count += shaderstaticparms_count;
1738
1739         // replace spaces in the cachename with _ characters
1740         for (i = 0;cachename[i];i++)
1741                 if (cachename[i] == ' ')
1742                         cachename[i] = '_';
1743
1744         // now append the shader text itself
1745         vertstrings_list[vertstrings_count++] = sourcestring;
1746         geomstrings_list[geomstrings_count++] = sourcestring;
1747         fragstrings_list[fragstrings_count++] = sourcestring;
1748
1749         vertstring_length = 0;
1750         for (i = 0;i < vertstrings_count;i++)
1751                 vertstring_length += strlen(vertstrings_list[i]);
1752         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1753         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1754                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1755
1756         geomstring_length = 0;
1757         for (i = 0;i < geomstrings_count;i++)
1758                 geomstring_length += strlen(geomstrings_list[i]);
1759         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1760         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1761                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1762
1763         fragstring_length = 0;
1764         for (i = 0;i < fragstrings_count;i++)
1765                 fragstring_length += strlen(fragstrings_list[i]);
1766         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1767         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1768                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1769
1770         // try to load the cached shader, or generate one
1771         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1772
1773         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1774                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1775         else
1776                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1777
1778         // free the strings
1779         if (vertstring)
1780                 Mem_Free(vertstring);
1781         if (geomstring)
1782                 Mem_Free(geomstring);
1783         if (fragstring)
1784                 Mem_Free(fragstring);
1785         if (sourcestring)
1786                 Mem_Free(sourcestring);
1787 }
1788
1789 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1790 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1791 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);}
1792 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);}
1793 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);}
1794 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);}
1795
1796 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1797 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1798 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);}
1799 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);}
1800 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);}
1801 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);}
1802
1803 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1804 {
1805         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1806         if (r_hlsl_permutation != perm)
1807         {
1808                 r_hlsl_permutation = perm;
1809                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1810                 {
1811                         if (!r_hlsl_permutation->compiled)
1812                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1813                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1814                         {
1815                                 // remove features until we find a valid permutation
1816                                 int i;
1817                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1818                                 {
1819                                         // reduce i more quickly whenever it would not remove any bits
1820                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1821                                         if (!(permutation & j))
1822                                                 continue;
1823                                         permutation -= j;
1824                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1825                                         if (!r_hlsl_permutation->compiled)
1826                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1827                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1828                                                 break;
1829                                 }
1830                                 if (i >= SHADERPERMUTATION_COUNT)
1831                                 {
1832                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1833                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1834                                         return; // no bit left to clear, entire mode is broken
1835                                 }
1836                         }
1837                 }
1838                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1839                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1840         }
1841         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1842         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1843         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1844 }
1845 #endif
1846
1847 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1848 {
1849         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1850         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1851         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1852         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1853 }
1854
1855 void R_GLSL_Restart_f(void)
1856 {
1857         unsigned int i, limit;
1858         if (glslshaderstring)
1859                 Mem_Free(glslshaderstring);
1860         glslshaderstring = NULL;
1861         if (hlslshaderstring)
1862                 Mem_Free(hlslshaderstring);
1863         hlslshaderstring = NULL;
1864         switch(vid.renderpath)
1865         {
1866         case RENDERPATH_D3D9:
1867 #ifdef SUPPORTD3D
1868                 {
1869                         r_hlsl_permutation_t *p;
1870                         r_hlsl_permutation = NULL;
1871                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1872                         for (i = 0;i < limit;i++)
1873                         {
1874                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1875                                 {
1876                                         if (p->vertexshader)
1877                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1878                                         if (p->pixelshader)
1879                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1880                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1881                                 }
1882                         }
1883                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1884                 }
1885 #endif
1886                 break;
1887         case RENDERPATH_D3D10:
1888                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1889                 break;
1890         case RENDERPATH_D3D11:
1891                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1892                 break;
1893         case RENDERPATH_GL20:
1894         case RENDERPATH_GLES2:
1895                 {
1896                         r_glsl_permutation_t *p;
1897                         r_glsl_permutation = NULL;
1898                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1899                         for (i = 0;i < limit;i++)
1900                         {
1901                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1902                                 {
1903                                         GL_Backend_FreeProgram(p->program);
1904                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1905                                 }
1906                         }
1907                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1908                 }
1909                 break;
1910         case RENDERPATH_GL11:
1911         case RENDERPATH_GL13:
1912         case RENDERPATH_GLES1:
1913                 break;
1914         case RENDERPATH_SOFT:
1915                 break;
1916         }
1917 }
1918
1919 static void R_GLSL_DumpShader_f(void)
1920 {
1921         int i, language, mode, dupe;
1922         char *text;
1923         shadermodeinfo_t *modeinfo;
1924         qfile_t *file;
1925
1926         for (language = 0;language < 2;language++)
1927         {
1928                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1929                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1930                 {
1931                         // don't dump the same file multiple times (most or all shaders come from the same file)
1932                         for (dupe = mode - 1;dupe >= 0;dupe--)
1933                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1934                                         break;
1935                         if (dupe >= 0)
1936                                 continue;
1937                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1938                         if (!text)
1939                                 continue;
1940                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1941                         if (file)
1942                         {
1943                                 FS_Print(file, "/* The engine may define the following macros:\n");
1944                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1945                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1946                                         FS_Print(file, modeinfo[i].pretext);
1947                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1948                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1949                                 FS_Print(file, "*/\n");
1950                                 FS_Print(file, text);
1951                                 FS_Close(file);
1952                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1953                         }
1954                         else
1955                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1956                         Mem_Free(text);
1957                 }
1958         }
1959 }
1960
1961 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1962 {
1963         unsigned int permutation = 0;
1964         if (r_trippy.integer && !notrippy)
1965                 permutation |= SHADERPERMUTATION_TRIPPY;
1966         permutation |= SHADERPERMUTATION_VIEWTINT;
1967         if (first)
1968                 permutation |= SHADERPERMUTATION_DIFFUSE;
1969         if (second)
1970                 permutation |= SHADERPERMUTATION_SPECULAR;
1971         if (texturemode == GL_MODULATE)
1972                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1973         else if (texturemode == GL_ADD)
1974                 permutation |= SHADERPERMUTATION_GLOW;
1975         else if (texturemode == GL_DECAL)
1976                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1977         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1978                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1979         if (suppresstexalpha)
1980                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1981         if (!second)
1982                 texturemode = GL_MODULATE;
1983         if (vid.allowalphatocoverage)
1984                 GL_AlphaToCoverage(false);
1985         switch (vid.renderpath)
1986         {
1987         case RENDERPATH_D3D9:
1988 #ifdef SUPPORTD3D
1989                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1990                 R_Mesh_TexBind(GL20TU_FIRST , first );
1991                 R_Mesh_TexBind(GL20TU_SECOND, second);
1992                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1993                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1994 #endif
1995                 break;
1996         case RENDERPATH_D3D10:
1997                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998                 break;
1999         case RENDERPATH_D3D11:
2000                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2001                 break;
2002         case RENDERPATH_GL20:
2003         case RENDERPATH_GLES2:
2004                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2005                 if (r_glsl_permutation->tex_Texture_First >= 0)
2006                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2007                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2008                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2009                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2010                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2011                 break;
2012         case RENDERPATH_GL13:
2013         case RENDERPATH_GLES1:
2014                 R_Mesh_TexBind(0, first );
2015                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2016                 R_Mesh_TexMatrix(0, NULL);
2017                 R_Mesh_TexBind(1, second);
2018                 if (second)
2019                 {
2020                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2021                         R_Mesh_TexMatrix(1, NULL);
2022                 }
2023                 break;
2024         case RENDERPATH_GL11:
2025                 R_Mesh_TexBind(0, first );
2026                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2027                 R_Mesh_TexMatrix(0, NULL);
2028                 break;
2029         case RENDERPATH_SOFT:
2030                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2031                 R_Mesh_TexBind(GL20TU_FIRST , first );
2032                 R_Mesh_TexBind(GL20TU_SECOND, second);
2033                 break;
2034         }
2035 }
2036
2037 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2038 {
2039         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2040 }
2041
2042 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2043 {
2044         unsigned int permutation = 0;
2045         if (r_trippy.integer && !notrippy)
2046                 permutation |= SHADERPERMUTATION_TRIPPY;
2047         if (depthrgb)
2048                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2049         if (skeletal)
2050                 permutation |= SHADERPERMUTATION_SKELETAL;
2051
2052         if (vid.allowalphatocoverage)
2053                 GL_AlphaToCoverage(false);
2054         switch (vid.renderpath)
2055         {
2056         case RENDERPATH_D3D9:
2057 #ifdef SUPPORTD3D
2058                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2059 #endif
2060                 break;
2061         case RENDERPATH_D3D10:
2062                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2063                 break;
2064         case RENDERPATH_D3D11:
2065                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2066                 break;
2067         case RENDERPATH_GL20:
2068         case RENDERPATH_GLES2:
2069                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2070                 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);
2071                 break;
2072         case RENDERPATH_GL13:
2073         case RENDERPATH_GLES1:
2074                 R_Mesh_TexBind(0, 0);
2075                 R_Mesh_TexBind(1, 0);
2076                 break;
2077         case RENDERPATH_GL11:
2078                 R_Mesh_TexBind(0, 0);
2079                 break;
2080         case RENDERPATH_SOFT:
2081                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2082                 break;
2083         }
2084 }
2085
2086 extern qboolean r_shadow_usingdeferredprepass;
2087 extern rtexture_t *r_shadow_attenuationgradienttexture;
2088 extern rtexture_t *r_shadow_attenuation2dtexture;
2089 extern rtexture_t *r_shadow_attenuation3dtexture;
2090 extern qboolean r_shadow_usingshadowmap2d;
2091 extern qboolean r_shadow_usingshadowmaportho;
2092 extern float r_shadow_shadowmap_texturescale[2];
2093 extern float r_shadow_shadowmap_parameters[4];
2094 extern qboolean r_shadow_shadowmapvsdct;
2095 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2096 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2097 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2098 extern matrix4x4_t r_shadow_shadowmapmatrix;
2099 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2100 extern int r_shadow_prepass_width;
2101 extern int r_shadow_prepass_height;
2102 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2103 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2104 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2105 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2106
2107 #define BLENDFUNC_ALLOWS_COLORMOD      1
2108 #define BLENDFUNC_ALLOWS_FOG           2
2109 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2110 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2111 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2112 static int R_BlendFuncFlags(int src, int dst)
2113 {
2114         int r = 0;
2115
2116         // a blendfunc allows colormod if:
2117         // a) it can never keep the destination pixel invariant, or
2118         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2119         // this is to prevent unintended side effects from colormod
2120
2121         // a blendfunc allows fog if:
2122         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2123         // this is to prevent unintended side effects from fog
2124
2125         // these checks are the output of fogeval.pl
2126
2127         r |= BLENDFUNC_ALLOWS_COLORMOD;
2128         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2129         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2130         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2132         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2133         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2134         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2135         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2136         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2137         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2138         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2139         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2140         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2141         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2142         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2143         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2144         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2145         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2146         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2147         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2148         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2149
2150         return r;
2151 }
2152
2153 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)
2154 {
2155         // select a permutation of the lighting shader appropriate to this
2156         // combination of texture, entity, light source, and fogging, only use the
2157         // minimum features necessary to avoid wasting rendering time in the
2158         // fragment shader on features that are not being used
2159         unsigned int permutation = 0;
2160         unsigned int mode = 0;
2161         int blendfuncflags;
2162         static float dummy_colormod[3] = {1, 1, 1};
2163         float *colormod = rsurface.colormod;
2164         float m16f[16];
2165         matrix4x4_t tempmatrix;
2166         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2167         if (r_trippy.integer && !notrippy)
2168                 permutation |= SHADERPERMUTATION_TRIPPY;
2169         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2170                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2171         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2172                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2173         if (rsurfacepass == RSURFPASS_BACKGROUND)
2174         {
2175                 // distorted background
2176                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2177                 {
2178                         mode = SHADERMODE_WATER;
2179                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2180                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2181                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2182                         {
2183                                 // this is the right thing to do for wateralpha
2184                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2185                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2186                         }
2187                         else
2188                         {
2189                                 // this is the right thing to do for entity alpha
2190                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2191                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2192                         }
2193                 }
2194                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2195                 {
2196                         mode = SHADERMODE_REFRACTION;
2197                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2198                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2199                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2200                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2201                 }
2202                 else
2203                 {
2204                         mode = SHADERMODE_GENERIC;
2205                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2206                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2207                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2208                 }
2209                 if (vid.allowalphatocoverage)
2210                         GL_AlphaToCoverage(false);
2211         }
2212         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2213         {
2214                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2215                 {
2216                         switch(rsurface.texture->offsetmapping)
2217                         {
2218                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2219                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2220                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221                         case OFFSETMAPPING_OFF: break;
2222                         }
2223                 }
2224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2225                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2226                 // normalmap (deferred prepass), may use alpha test on diffuse
2227                 mode = SHADERMODE_DEFERREDGEOMETRY;
2228                 GL_BlendFunc(GL_ONE, GL_ZERO);
2229                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2230                 if (vid.allowalphatocoverage)
2231                         GL_AlphaToCoverage(false);
2232         }
2233         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2234         {
2235                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2236                 {
2237                         switch(rsurface.texture->offsetmapping)
2238                         {
2239                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2240                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_OFF: break;
2243                         }
2244                 }
2245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2246                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2248                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2249                 // light source
2250                 mode = SHADERMODE_LIGHTSOURCE;
2251                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2252                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2253                 if (diffusescale > 0)
2254                         permutation |= SHADERPERMUTATION_DIFFUSE;
2255                 if (specularscale > 0)
2256                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2257                 if (r_refdef.fogenabled)
2258                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259                 if (rsurface.texture->colormapping)
2260                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2261                 if (r_shadow_usingshadowmap2d)
2262                 {
2263                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2264                         if(r_shadow_shadowmapvsdct)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2266
2267                         if (r_shadow_shadowmap2ddepthbuffer)
2268                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2269                 }
2270                 if (rsurface.texture->reflectmasktexture)
2271                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2272                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2273                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2274                 if (vid.allowalphatocoverage)
2275                         GL_AlphaToCoverage(false);
2276         }
2277         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2278         {
2279                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2280                 {
2281                         switch(rsurface.texture->offsetmapping)
2282                         {
2283                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_OFF: break;
2287                         }
2288                 }
2289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2292                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2293                 // unshaded geometry (fullbright or ambient model lighting)
2294                 mode = SHADERMODE_FLATCOLOR;
2295                 ambientscale = diffusescale = specularscale = 0;
2296                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2297                         permutation |= SHADERPERMUTATION_GLOW;
2298                 if (r_refdef.fogenabled)
2299                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300                 if (rsurface.texture->colormapping)
2301                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2302                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2303                 {
2304                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2306
2307                         if (r_shadow_shadowmap2ddepthbuffer)
2308                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2309                 }
2310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2311                         permutation |= SHADERPERMUTATION_REFLECTION;
2312                 if (rsurface.texture->reflectmasktexture)
2313                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2314                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2315                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2316                 // when using alphatocoverage, we don't need alphakill
2317                 if (vid.allowalphatocoverage)
2318                 {
2319                         if (r_transparent_alphatocoverage.integer)
2320                         {
2321                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2322                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2323                         }
2324                         else
2325                                 GL_AlphaToCoverage(false);
2326                 }
2327         }
2328         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2329         {
2330                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2331                 {
2332                         switch(rsurface.texture->offsetmapping)
2333                         {
2334                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2335                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2336                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2337                         case OFFSETMAPPING_OFF: break;
2338                         }
2339                 }
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2341                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2343                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2344                 // directional model lighting
2345                 mode = SHADERMODE_LIGHTDIRECTION;
2346                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2347                         permutation |= SHADERPERMUTATION_GLOW;
2348                 permutation |= SHADERPERMUTATION_DIFFUSE;
2349                 if (specularscale > 0)
2350                         permutation |= SHADERPERMUTATION_SPECULAR;
2351                 if (r_refdef.fogenabled)
2352                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2353                 if (rsurface.texture->colormapping)
2354                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2355                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2356                 {
2357                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2358                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2359
2360                         if (r_shadow_shadowmap2ddepthbuffer)
2361                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2362                 }
2363                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2364                         permutation |= SHADERPERMUTATION_REFLECTION;
2365                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2366                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2367                 if (rsurface.texture->reflectmasktexture)
2368                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2370                 {
2371                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2372                         if (r_shadow_bouncegriddirectional)
2373                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2374                 }
2375                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2376                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2377                 // when using alphatocoverage, we don't need alphakill
2378                 if (vid.allowalphatocoverage)
2379                 {
2380                         if (r_transparent_alphatocoverage.integer)
2381                         {
2382                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2383                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2384                         }
2385                         else
2386                                 GL_AlphaToCoverage(false);
2387                 }
2388         }
2389         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2390         {
2391                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2392                 {
2393                         switch(rsurface.texture->offsetmapping)
2394                         {
2395                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2396                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2397                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2398                         case OFFSETMAPPING_OFF: break;
2399                         }
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2402                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2404                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2405                 // ambient model lighting
2406                 mode = SHADERMODE_LIGHTDIRECTION;
2407                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2408                         permutation |= SHADERPERMUTATION_GLOW;
2409                 if (r_refdef.fogenabled)
2410                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2411                 if (rsurface.texture->colormapping)
2412                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2413                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2414                 {
2415                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2416                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2417
2418                         if (r_shadow_shadowmap2ddepthbuffer)
2419                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2420                 }
2421                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2422                         permutation |= SHADERPERMUTATION_REFLECTION;
2423                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2424                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2425                 if (rsurface.texture->reflectmasktexture)
2426                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2427                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2428                 {
2429                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2430                         if (r_shadow_bouncegriddirectional)
2431                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2432                 }
2433                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2434                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435                 // when using alphatocoverage, we don't need alphakill
2436                 if (vid.allowalphatocoverage)
2437                 {
2438                         if (r_transparent_alphatocoverage.integer)
2439                         {
2440                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2441                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2442                         }
2443                         else
2444                                 GL_AlphaToCoverage(false);
2445                 }
2446         }
2447         else
2448         {
2449                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2450                 {
2451                         switch(rsurface.texture->offsetmapping)
2452                         {
2453                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2454                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2455                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456                         case OFFSETMAPPING_OFF: break;
2457                         }
2458                 }
2459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2460                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2462                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2463                 // lightmapped wall
2464                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2465                         permutation |= SHADERPERMUTATION_GLOW;
2466                 if (r_refdef.fogenabled)
2467                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2468                 if (rsurface.texture->colormapping)
2469                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2470                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2471                 {
2472                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2473                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2474
2475                         if (r_shadow_shadowmap2ddepthbuffer)
2476                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2477                 }
2478                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2479                         permutation |= SHADERPERMUTATION_REFLECTION;
2480                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2481                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2482                 if (rsurface.texture->reflectmasktexture)
2483                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2484                 if (FAKELIGHT_ENABLED)
2485                 {
2486                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2487                         mode = SHADERMODE_FAKELIGHT;
2488                         permutation |= SHADERPERMUTATION_DIFFUSE;
2489                         if (specularscale > 0)
2490                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2491                 }
2492                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2493                 {
2494                         // deluxemapping (light direction texture)
2495                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2496                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2497                         else
2498                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2499                         permutation |= SHADERPERMUTATION_DIFFUSE;
2500                         if (specularscale > 0)
2501                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2502                 }
2503                 else if (r_glsl_deluxemapping.integer >= 2)
2504                 {
2505                         // fake deluxemapping (uniform light direction in tangentspace)
2506                         if (rsurface.uselightmaptexture)
2507                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2508                         else
2509                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2510                         permutation |= SHADERPERMUTATION_DIFFUSE;
2511                         if (specularscale > 0)
2512                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2513                 }
2514                 else if (rsurface.uselightmaptexture)
2515                 {
2516                         // ordinary lightmapping (q1bsp, q3bsp)
2517                         mode = SHADERMODE_LIGHTMAP;
2518                 }
2519                 else
2520                 {
2521                         // ordinary vertex coloring (q3bsp)
2522                         mode = SHADERMODE_VERTEXCOLOR;
2523                 }
2524                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2525                 {
2526                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2527                         if (r_shadow_bouncegriddirectional)
2528                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2529                 }
2530                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2531                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2532                 // when using alphatocoverage, we don't need alphakill
2533                 if (vid.allowalphatocoverage)
2534                 {
2535                         if (r_transparent_alphatocoverage.integer)
2536                         {
2537                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2538                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2539                         }
2540                         else
2541                                 GL_AlphaToCoverage(false);
2542                 }
2543         }
2544         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2545                 colormod = dummy_colormod;
2546         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2547                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2548         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2549                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2550         switch(vid.renderpath)
2551         {
2552         case RENDERPATH_D3D9:
2553 #ifdef SUPPORTD3D
2554                 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);
2555                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2556                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2557                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2558                 if (mode == SHADERMODE_LIGHTSOURCE)
2559                 {
2560                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2561                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2562                 }
2563                 else
2564                 {
2565                         if (mode == SHADERMODE_LIGHTDIRECTION)
2566                         {
2567                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2568                         }
2569                 }
2570                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2571                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2572                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2573                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2574                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2575
2576                 if (mode == SHADERMODE_LIGHTSOURCE)
2577                 {
2578                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2579                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2580                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2581                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2582                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2583
2584                         // additive passes are only darkened by fog, not tinted
2585                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2587                 }
2588                 else
2589                 {
2590                         if (mode == SHADERMODE_FLATCOLOR)
2591                         {
2592                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2593                         }
2594                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2595                         {
2596                                 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]);
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2598                                 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);
2599                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2600                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2601                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2602                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2603                         }
2604                         else
2605                         {
2606                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2607                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2608                                 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);
2609                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2610                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2611                         }
2612                         // additive passes are only darkened by fog, not tinted
2613                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2614                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2615                         else
2616                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2617                         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);
2618                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2619                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2620                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2621                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2622                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2623                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2624                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2625                         if (mode == SHADERMODE_WATER)
2626                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2627                 }
2628                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2629                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2630                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2631                 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));
2632                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2633                 if (rsurface.texture->pantstexture)
2634                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2635                 else
2636                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2637                 if (rsurface.texture->shirttexture)
2638                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2639                 else
2640                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2641                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2642                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2643                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2644                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2645                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2646                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2647                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2648                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2649                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2650                         );
2651                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2652                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2653                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2654                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2655
2656                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2657                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2658                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2659                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2660                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2661                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2662                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2663                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2664                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2665                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2666                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2667                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2668                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2669                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2670                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2671                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2672                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2673                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2674                 {
2675                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2676                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2677                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2678                 }
2679                 else
2680                 {
2681                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2682                 }
2683 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2684                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2685                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2686                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2687                 {
2688                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2689                         if (rsurface.rtlight)
2690                         {
2691                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2692                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2693                         }
2694                 }
2695 #endif
2696                 break;
2697         case RENDERPATH_D3D10:
2698                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2699                 break;
2700         case RENDERPATH_D3D11:
2701                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2702                 break;
2703         case RENDERPATH_GL20:
2704         case RENDERPATH_GLES2:
2705                 if (!vid.useinterleavedarrays)
2706                 {
2707                         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);
2708                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2709                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2710                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2711                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2712                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2713                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2714                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2715                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2716                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2717                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2718                 }
2719                 else
2720                 {
2721                         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);
2722                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2723                 }
2724                 // this has to be after RSurf_PrepareVerticesForBatch
2725                 if (rsurface.batchskeletaltransform3x4buffer)
2726                         permutation |= SHADERPERMUTATION_SKELETAL;
2727                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2728                 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);
2729                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2730                 if (mode == SHADERMODE_LIGHTSOURCE)
2731                 {
2732                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2733                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2734                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2735                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2736                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2737                         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);
2738         
2739                         // additive passes are only darkened by fog, not tinted
2740                         if (r_glsl_permutation->loc_FogColor >= 0)
2741                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2742                         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);
2743                 }
2744                 else
2745                 {
2746                         if (mode == SHADERMODE_FLATCOLOR)
2747                         {
2748                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2749                         }
2750                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2751                         {
2752                                 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]);
2753                                 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]);
2754                                 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);
2755                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2756                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2757                                 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]);
2758                                 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]);
2759                         }
2760                         else
2761                         {
2762                                 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]);
2763                                 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]);
2764                                 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);
2765                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2766                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2767                         }
2768                         // additive passes are only darkened by fog, not tinted
2769                         if (r_glsl_permutation->loc_FogColor >= 0)
2770                         {
2771                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2772                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2773                                 else
2774                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2775                         }
2776                         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);
2777                         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]);
2778                         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]);
2779                         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]);
2780                         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]);
2781                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2782                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2783                         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);
2784                         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]);
2785                 }
2786                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2787                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2788                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2789                 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]);
2790                 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]);
2791
2792                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2793                 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));
2794                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2795                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2796                 {
2797                         if (rsurface.texture->pantstexture)
2798                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2799                         else
2800                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2801                 }
2802                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2803                 {
2804                         if (rsurface.texture->shirttexture)
2805                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2806                         else
2807                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2808                 }
2809                 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]);
2810                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2811                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2812                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2813                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2814                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2815                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2816                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2817                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2818                         );
2819                 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);
2820                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2821                 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]);
2822                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2823                 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);}
2824                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2825
2826                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2827                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2828                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2829                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2830                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2831                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2832                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2833                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2834                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2835                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2836                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2837                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2838                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2839                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2840                 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);
2841                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2842                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2843                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2844                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2845                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2846                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2847                 {
2848                         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);
2849                         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);
2850                         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);
2851                 }
2852                 else
2853                 {
2854                         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);
2855                 }
2856                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2857                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2858                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2859                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2860                 {
2861                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2862                         if (rsurface.rtlight)
2863                         {
2864                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2865                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2866                         }
2867                 }
2868                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2869                 CHECKGLERROR
2870                 break;
2871         case RENDERPATH_GL11:
2872         case RENDERPATH_GL13:
2873         case RENDERPATH_GLES1:
2874                 break;
2875         case RENDERPATH_SOFT:
2876                 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);
2877                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2878                 R_SetupShader_SetPermutationSoft(mode, permutation);
2879                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2880                 if (mode == SHADERMODE_LIGHTSOURCE)
2881                 {
2882                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2883                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2884                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2885                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2886                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2887                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2888         
2889                         // additive passes are only darkened by fog, not tinted
2890                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2891                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2892                 }
2893                 else
2894                 {
2895                         if (mode == SHADERMODE_FLATCOLOR)
2896                         {
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2898                         }
2899                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2900                         {
2901                                 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]);
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2903                                 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);
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2906                                 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]);
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2908                         }
2909                         else
2910                         {
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2913                                 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);
2914                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2916                         }
2917                         // additive passes are only darkened by fog, not tinted
2918                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2920                         else
2921                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2922                         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);
2923                         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]);
2924                         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]);
2925                         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]);
2926                         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]);
2927                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2928                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2929                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2930                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2931                 }
2932                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2933                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2934                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2935                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2936                 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]);
2937
2938                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2939                 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));
2940                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2941                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2942                 {
2943                         if (rsurface.texture->pantstexture)
2944                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2945                         else
2946                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2947                 }
2948                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2949                 {
2950                         if (rsurface.texture->shirttexture)
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2952                         else
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2954                 }
2955                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2956                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2957                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2958                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2959                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2960                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2961                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2962                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2963                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2964                         );
2965                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2966                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2967                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2969
2970                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2971                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2972                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2973                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2974                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2975                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2976                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2977                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2978                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2979                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2980                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2981                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2982                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2983                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2984                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2985                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2986                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2987                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2988                 {
2989                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2990                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2991                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2992                 }
2993                 else
2994                 {
2995                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2996                 }
2997 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2998                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2999                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3000                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3001                 {
3002                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3003                         if (rsurface.rtlight)
3004                         {
3005                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3006                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3007                         }
3008                 }
3009                 break;
3010         }
3011 }
3012
3013 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3014 {
3015         // select a permutation of the lighting shader appropriate to this
3016         // combination of texture, entity, light source, and fogging, only use the
3017         // minimum features necessary to avoid wasting rendering time in the
3018         // fragment shader on features that are not being used
3019         unsigned int permutation = 0;
3020         unsigned int mode = 0;
3021         const float *lightcolorbase = rtlight->currentcolor;
3022         float ambientscale = rtlight->ambientscale;
3023         float diffusescale = rtlight->diffusescale;
3024         float specularscale = rtlight->specularscale;
3025         // this is the location of the light in view space
3026         vec3_t viewlightorigin;
3027         // this transforms from view space (camera) to light space (cubemap)
3028         matrix4x4_t viewtolight;
3029         matrix4x4_t lighttoview;
3030         float viewtolight16f[16];
3031         // light source
3032         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3033         if (rtlight->currentcubemap != r_texture_whitecube)
3034                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3035         if (diffusescale > 0)
3036                 permutation |= SHADERPERMUTATION_DIFFUSE;
3037         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3038                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3039         if (r_shadow_usingshadowmap2d)
3040         {
3041                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3042                 if (r_shadow_shadowmapvsdct)
3043                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3044
3045                 if (r_shadow_shadowmap2ddepthbuffer)
3046                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3047         }
3048         if (vid.allowalphatocoverage)
3049                 GL_AlphaToCoverage(false);
3050         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3051         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3052         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3053         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3054         switch(vid.renderpath)
3055         {
3056         case RENDERPATH_D3D9:
3057 #ifdef SUPPORTD3D
3058                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3059                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3060                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3061                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3062                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3063                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3064                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3065                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3066                 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);
3067                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3068                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3069
3070                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3071                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3073                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3074                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3075 #endif
3076                 break;
3077         case RENDERPATH_D3D10:
3078                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3079                 break;
3080         case RENDERPATH_D3D11:
3081                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3082                 break;
3083         case RENDERPATH_GL20:
3084         case RENDERPATH_GLES2:
3085                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3086                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3087                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3088                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3089                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3090                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3091                 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]);
3092                 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]);
3093                 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);
3094                 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]);
3095                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3096
3097                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3098                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3099                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3100                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3101                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3102                 break;
3103         case RENDERPATH_GL11:
3104         case RENDERPATH_GL13:
3105         case RENDERPATH_GLES1:
3106                 break;
3107         case RENDERPATH_SOFT:
3108                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3109                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3110                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3111                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3112                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3113                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3114                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3115                 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]);
3116                 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);
3117                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3118                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3119
3120                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3121                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3122                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3123                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3124                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3125                 break;
3126         }
3127 }
3128
3129 #define SKINFRAME_HASH 1024
3130
3131 typedef struct
3132 {
3133         int loadsequence; // incremented each level change
3134         memexpandablearray_t array;
3135         skinframe_t *hash[SKINFRAME_HASH];
3136 }
3137 r_skinframe_t;
3138 r_skinframe_t r_skinframe;
3139
3140 void R_SkinFrame_PrepareForPurge(void)
3141 {
3142         r_skinframe.loadsequence++;
3143         // wrap it without hitting zero
3144         if (r_skinframe.loadsequence >= 200)
3145                 r_skinframe.loadsequence = 1;
3146 }
3147
3148 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3149 {
3150         if (!skinframe)
3151                 return;
3152         // mark the skinframe as used for the purging code
3153         skinframe->loadsequence = r_skinframe.loadsequence;
3154 }
3155
3156 void R_SkinFrame_Purge(void)
3157 {
3158         int i;
3159         skinframe_t *s;
3160         for (i = 0;i < SKINFRAME_HASH;i++)
3161         {
3162                 for (s = r_skinframe.hash[i];s;s = s->next)
3163                 {
3164                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3165                         {
3166                                 if (s->merged == s->base)
3167                                         s->merged = NULL;
3168                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3169                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3170                                 R_PurgeTexture(s->merged);s->merged = NULL;
3171                                 R_PurgeTexture(s->base  );s->base   = NULL;
3172                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3173                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3174                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3175                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3176                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3177                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3178                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3179                                 s->loadsequence = 0;
3180                         }
3181                 }
3182         }
3183 }
3184
3185 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3186         skinframe_t *item;
3187         char basename[MAX_QPATH];
3188
3189         Image_StripImageExtension(name, basename, sizeof(basename));
3190
3191         if( last == NULL ) {
3192                 int hashindex;
3193                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3194                 item = r_skinframe.hash[hashindex];
3195         } else {
3196                 item = last->next;
3197         }
3198
3199         // linearly search through the hash bucket
3200         for( ; item ; item = item->next ) {
3201                 if( !strcmp( item->basename, basename ) ) {
3202                         return item;
3203                 }
3204         }
3205         return NULL;
3206 }
3207
3208 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3209 {
3210         skinframe_t *item;
3211         int hashindex;
3212         char basename[MAX_QPATH];
3213
3214         Image_StripImageExtension(name, basename, sizeof(basename));
3215
3216         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3217         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3218                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3219                         break;
3220
3221         if (!item) {
3222                 rtexture_t *dyntexture;
3223                 // check whether its a dynamic texture
3224                 dyntexture = CL_GetDynTexture( basename );
3225                 if (!add && !dyntexture)
3226                         return NULL;
3227                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3228                 memset(item, 0, sizeof(*item));
3229                 strlcpy(item->basename, basename, sizeof(item->basename));
3230                 item->base = dyntexture; // either NULL or dyntexture handle
3231                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3232                 item->comparewidth = comparewidth;
3233                 item->compareheight = compareheight;
3234                 item->comparecrc = comparecrc;
3235                 item->next = r_skinframe.hash[hashindex];
3236                 r_skinframe.hash[hashindex] = item;
3237         }
3238         else if (textureflags & TEXF_FORCE_RELOAD)
3239         {
3240                 rtexture_t *dyntexture;
3241                 // check whether its a dynamic texture
3242                 dyntexture = CL_GetDynTexture( basename );
3243                 if (!add && !dyntexture)
3244                         return NULL;
3245                 if (item->merged == item->base)
3246                         item->merged = NULL;
3247                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3248                 R_PurgeTexture(item->stain );item->stain  = NULL;
3249                 R_PurgeTexture(item->merged);item->merged = NULL;
3250                 R_PurgeTexture(item->base  );item->base   = NULL;
3251                 R_PurgeTexture(item->pants );item->pants  = NULL;
3252                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3253                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3254                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3255                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3256                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3257         R_PurgeTexture(item->reflect);item->reflect = NULL;
3258                 item->loadsequence = 0;
3259         }
3260         else if( item->base == NULL )
3261         {
3262                 rtexture_t *dyntexture;
3263                 // check whether its a dynamic texture
3264                 // 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]
3265                 dyntexture = CL_GetDynTexture( basename );
3266                 item->base = dyntexture; // either NULL or dyntexture handle
3267         }
3268
3269         R_SkinFrame_MarkUsed(item);
3270         return item;
3271 }
3272
3273 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3274         { \
3275                 unsigned long long avgcolor[5], wsum; \
3276                 int pix, comp, w; \
3277                 avgcolor[0] = 0; \
3278                 avgcolor[1] = 0; \
3279                 avgcolor[2] = 0; \
3280                 avgcolor[3] = 0; \
3281                 avgcolor[4] = 0; \
3282                 wsum = 0; \
3283                 for(pix = 0; pix < cnt; ++pix) \
3284                 { \
3285                         w = 0; \
3286                         for(comp = 0; comp < 3; ++comp) \
3287                                 w += getpixel; \
3288                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3289                         { \
3290                                 ++wsum; \
3291                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3292                                 w = getpixel; \
3293                                 for(comp = 0; comp < 3; ++comp) \
3294                                         avgcolor[comp] += getpixel * w; \
3295                                 avgcolor[3] += w; \
3296                         } \
3297                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3298                         avgcolor[4] += getpixel; \
3299                 } \
3300                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3301                         avgcolor[3] = 1; \
3302                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3303                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3304                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3305                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3306         }
3307
3308 extern cvar_t gl_picmip;
3309 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3310 {
3311         int j;
3312         unsigned char *pixels;
3313         unsigned char *bumppixels;
3314         unsigned char *basepixels = NULL;
3315         int basepixels_width = 0;
3316         int basepixels_height = 0;
3317         skinframe_t *skinframe;
3318         rtexture_t *ddsbase = NULL;
3319         qboolean ddshasalpha = false;
3320         float ddsavgcolor[4];
3321         char basename[MAX_QPATH];
3322         int miplevel = R_PicmipForFlags(textureflags);
3323         int savemiplevel = miplevel;
3324         int mymiplevel;
3325         char vabuf[1024];
3326
3327         if (cls.state == ca_dedicated)
3328                 return NULL;
3329
3330         // return an existing skinframe if already loaded
3331         // if loading of the first image fails, don't make a new skinframe as it
3332         // would cause all future lookups of this to be missing
3333         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3334         if (skinframe && skinframe->base)
3335                 return skinframe;
3336
3337         Image_StripImageExtension(name, basename, sizeof(basename));
3338
3339         // check for DDS texture file first
3340         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3341         {
3342                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3343                 if (basepixels == NULL)
3344                         return NULL;
3345         }
3346
3347         // FIXME handle miplevel
3348
3349         if (developer_loading.integer)
3350                 Con_Printf("loading skin \"%s\"\n", name);
3351
3352         // we've got some pixels to store, so really allocate this new texture now
3353         if (!skinframe)
3354                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3355         textureflags &= ~TEXF_FORCE_RELOAD;
3356         skinframe->stain = NULL;
3357         skinframe->merged = NULL;
3358         skinframe->base = NULL;
3359         skinframe->pants = NULL;
3360         skinframe->shirt = NULL;
3361         skinframe->nmap = NULL;
3362         skinframe->gloss = NULL;
3363         skinframe->glow = NULL;
3364         skinframe->fog = NULL;
3365         skinframe->reflect = NULL;
3366         skinframe->hasalpha = false;
3367
3368         if (ddsbase)
3369         {
3370                 skinframe->base = ddsbase;
3371                 skinframe->hasalpha = ddshasalpha;
3372                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3373                 if (r_loadfog && skinframe->hasalpha)
3374                         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);
3375                 //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]);
3376         }
3377         else
3378         {
3379                 basepixels_width = image_width;
3380                 basepixels_height = image_height;
3381                 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);
3382                 if (textureflags & TEXF_ALPHA)
3383                 {
3384                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3385                         {
3386                                 if (basepixels[j] < 255)
3387                                 {
3388                                         skinframe->hasalpha = true;
3389                                         break;
3390                                 }
3391                         }
3392                         if (r_loadfog && skinframe->hasalpha)
3393                         {
3394                                 // has transparent pixels
3395                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3396                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3397                                 {
3398                                         pixels[j+0] = 255;
3399                                         pixels[j+1] = 255;
3400                                         pixels[j+2] = 255;
3401                                         pixels[j+3] = basepixels[j+3];
3402                                 }
3403                                 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);
3404                                 Mem_Free(pixels);
3405                         }
3406                 }
3407                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3408 #ifndef USE_GLES2
3409                 //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]);
3410                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3411                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3413                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3414 #endif
3415         }
3416
3417         if (r_loaddds)
3418         {
3419                 mymiplevel = savemiplevel;
3420                 if (r_loadnormalmap)
3421                         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);
3422                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3423                 if (r_loadgloss)
3424                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3425                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3426                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3427                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3428         }
3429
3430         // _norm is the name used by tenebrae and has been adopted as standard
3431         if (r_loadnormalmap && skinframe->nmap == NULL)
3432         {
3433                 mymiplevel = savemiplevel;
3434                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3435                 {
3436                         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);
3437                         Mem_Free(pixels);
3438                         pixels = NULL;
3439                 }
3440                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3441                 {
3442                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3443                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3444                         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);
3445                         Mem_Free(pixels);
3446                         Mem_Free(bumppixels);
3447                 }
3448                 else if (r_shadow_bumpscale_basetexture.value > 0)
3449                 {
3450                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3451                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3452                         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);
3453                         Mem_Free(pixels);
3454                 }
3455 #ifndef USE_GLES2
3456                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3457                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3458 #endif
3459         }
3460
3461         // _luma is supported only for tenebrae compatibility
3462         // _glow is the preferred name
3463         mymiplevel = savemiplevel;
3464         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))))
3465         {
3466                 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);
3467 #ifndef USE_GLES2
3468                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3469                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3470 #endif
3471                 Mem_Free(pixels);pixels = NULL;
3472         }
3473
3474         mymiplevel = savemiplevel;
3475         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3476         {
3477                 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);
3478 #ifndef USE_GLES2
3479                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3480                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3481 #endif
3482                 Mem_Free(pixels);
3483                 pixels = NULL;
3484         }
3485
3486         mymiplevel = savemiplevel;
3487         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3488         {
3489                 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);
3490 #ifndef USE_GLES2
3491                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3492                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3493 #endif
3494                 Mem_Free(pixels);
3495                 pixels = NULL;
3496         }
3497
3498         mymiplevel = savemiplevel;
3499         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3500         {
3501                 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);
3502 #ifndef USE_GLES2
3503                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3504                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3505 #endif
3506                 Mem_Free(pixels);
3507                 pixels = NULL;
3508         }
3509
3510         mymiplevel = savemiplevel;
3511         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3512         {
3513                 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);
3514 #ifndef USE_GLES2
3515                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3516                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3517 #endif
3518                 Mem_Free(pixels);
3519                 pixels = NULL;
3520         }
3521
3522         if (basepixels)
3523                 Mem_Free(basepixels);
3524
3525         return skinframe;
3526 }
3527
3528 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3529 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3530 {
3531         int i;
3532         unsigned char *temp1, *temp2;
3533         skinframe_t *skinframe;
3534         char vabuf[1024];
3535
3536         if (cls.state == ca_dedicated)
3537                 return NULL;
3538
3539         // if already loaded just return it, otherwise make a new skinframe
3540         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3541         if (skinframe->base)
3542                 return skinframe;
3543         textureflags &= ~TEXF_FORCE_RELOAD;
3544
3545         skinframe->stain = NULL;
3546         skinframe->merged = NULL;
3547         skinframe->base = NULL;
3548         skinframe->pants = NULL;
3549         skinframe->shirt = NULL;
3550         skinframe->nmap = NULL;
3551         skinframe->gloss = NULL;
3552         skinframe->glow = NULL;
3553         skinframe->fog = NULL;
3554         skinframe->reflect = NULL;
3555         skinframe->hasalpha = false;
3556
3557         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3558         if (!skindata)
3559                 return NULL;
3560
3561         if (developer_loading.integer)
3562                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3563
3564         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3565         {
3566                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3567                 temp2 = temp1 + width * height * 4;
3568                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3569                 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);
3570                 Mem_Free(temp1);
3571         }
3572         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3573         if (textureflags & TEXF_ALPHA)
3574         {
3575                 for (i = 3;i < width * height * 4;i += 4)
3576                 {
3577                         if (skindata[i] < 255)
3578                         {
3579                                 skinframe->hasalpha = true;
3580                                 break;
3581                         }
3582                 }
3583                 if (r_loadfog && skinframe->hasalpha)
3584                 {
3585                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3586                         memcpy(fogpixels, skindata, width * height * 4);
3587                         for (i = 0;i < width * height * 4;i += 4)
3588                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3589                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3590                         Mem_Free(fogpixels);
3591                 }
3592         }
3593
3594         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3595         //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]);
3596
3597         return skinframe;
3598 }
3599
3600 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3601 {
3602         int i;
3603         int featuresmask;
3604         skinframe_t *skinframe;
3605
3606         if (cls.state == ca_dedicated)
3607                 return NULL;
3608
3609         // if already loaded just return it, otherwise make a new skinframe
3610         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3611         if (skinframe->base)
3612                 return skinframe;
3613         //textureflags &= ~TEXF_FORCE_RELOAD;
3614
3615         skinframe->stain = NULL;
3616         skinframe->merged = NULL;
3617         skinframe->base = NULL;
3618         skinframe->pants = NULL;
3619         skinframe->shirt = NULL;
3620         skinframe->nmap = NULL;
3621         skinframe->gloss = NULL;
3622         skinframe->glow = NULL;
3623         skinframe->fog = NULL;
3624         skinframe->reflect = NULL;
3625         skinframe->hasalpha = false;
3626
3627         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3628         if (!skindata)
3629                 return NULL;
3630
3631         if (developer_loading.integer)
3632                 Con_Printf("loading quake skin \"%s\"\n", name);
3633
3634         // 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)
3635         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3636         memcpy(skinframe->qpixels, skindata, width*height);
3637         skinframe->qwidth = width;
3638         skinframe->qheight = height;
3639
3640         featuresmask = 0;
3641         for (i = 0;i < width * height;i++)
3642                 featuresmask |= palette_featureflags[skindata[i]];
3643
3644         skinframe->hasalpha = false;
3645         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3646         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3647         skinframe->qgeneratemerged = true;
3648         skinframe->qgeneratebase = skinframe->qhascolormapping;
3649         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3650
3651         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3652         //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]);
3653
3654         return skinframe;
3655 }
3656
3657 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3658 {
3659         int width;
3660         int height;
3661         unsigned char *skindata;
3662         char vabuf[1024];
3663
3664         if (!skinframe->qpixels)
3665                 return;
3666
3667         if (!skinframe->qhascolormapping)
3668                 colormapped = false;
3669
3670         if (colormapped)
3671         {
3672                 if (!skinframe->qgeneratebase)
3673                         return;
3674         }
3675         else
3676         {
3677                 if (!skinframe->qgeneratemerged)
3678                         return;
3679         }
3680
3681         width = skinframe->qwidth;
3682         height = skinframe->qheight;
3683         skindata = skinframe->qpixels;
3684
3685         if (skinframe->qgeneratenmap)
3686         {
3687                 unsigned char *temp1, *temp2;
3688                 skinframe->qgeneratenmap = false;
3689                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3690                 temp2 = temp1 + width * height * 4;
3691                 // use either a custom palette or the quake palette
3692                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3693                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3694                 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);
3695                 Mem_Free(temp1);
3696         }
3697
3698         if (skinframe->qgenerateglow)
3699         {
3700                 skinframe->qgenerateglow = false;
3701                 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
3702         }
3703
3704         if (colormapped)
3705         {
3706                 skinframe->qgeneratebase = false;
3707                 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);
3708                 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);
3709                 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);
3710         }
3711         else
3712         {
3713                 skinframe->qgeneratemerged = false;
3714                 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);
3715         }
3716
3717         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3718         {
3719                 Mem_Free(skinframe->qpixels);
3720                 skinframe->qpixels = NULL;
3721         }
3722 }
3723
3724 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)
3725 {
3726         int i;
3727         skinframe_t *skinframe;
3728         char vabuf[1024];
3729
3730         if (cls.state == ca_dedicated)
3731                 return NULL;
3732
3733         // if already loaded just return it, otherwise make a new skinframe
3734         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3735         if (skinframe->base)
3736                 return skinframe;
3737         textureflags &= ~TEXF_FORCE_RELOAD;
3738
3739         skinframe->stain = NULL;
3740         skinframe->merged = NULL;
3741         skinframe->base = NULL;
3742         skinframe->pants = NULL;
3743         skinframe->shirt = NULL;
3744         skinframe->nmap = NULL;
3745         skinframe->gloss = NULL;
3746         skinframe->glow = NULL;
3747         skinframe->fog = NULL;
3748         skinframe->reflect = NULL;
3749         skinframe->hasalpha = false;
3750
3751         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3752         if (!skindata)
3753                 return NULL;
3754
3755         if (developer_loading.integer)
3756                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3757
3758         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3759         if (textureflags & TEXF_ALPHA)
3760         {
3761                 for (i = 0;i < width * height;i++)
3762                 {
3763                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3764                         {
3765                                 skinframe->hasalpha = true;
3766                                 break;
3767                         }
3768                 }
3769                 if (r_loadfog && skinframe->hasalpha)
3770                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3771         }
3772
3773         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3774         //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]);
3775
3776         return skinframe;
3777 }
3778
3779 skinframe_t *R_SkinFrame_LoadMissing(void)
3780 {
3781         skinframe_t *skinframe;
3782
3783         if (cls.state == ca_dedicated)
3784                 return NULL;
3785
3786         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3787         skinframe->stain = NULL;
3788         skinframe->merged = NULL;
3789         skinframe->base = NULL;
3790         skinframe->pants = NULL;
3791         skinframe->shirt = NULL;
3792         skinframe->nmap = NULL;
3793         skinframe->gloss = NULL;
3794         skinframe->glow = NULL;
3795         skinframe->fog = NULL;
3796         skinframe->reflect = NULL;
3797         skinframe->hasalpha = false;
3798
3799         skinframe->avgcolor[0] = rand() / RAND_MAX;
3800         skinframe->avgcolor[1] = rand() / RAND_MAX;
3801         skinframe->avgcolor[2] = rand() / RAND_MAX;
3802         skinframe->avgcolor[3] = 1;
3803
3804         return skinframe;
3805 }
3806
3807 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3808 typedef struct suffixinfo_s
3809 {
3810         const char *suffix;
3811         qboolean flipx, flipy, flipdiagonal;
3812 }
3813 suffixinfo_t;
3814 static suffixinfo_t suffix[3][6] =
3815 {
3816         {
3817                 {"px",   false, false, false},
3818                 {"nx",   false, false, false},
3819                 {"py",   false, false, false},
3820                 {"ny",   false, false, false},
3821                 {"pz",   false, false, false},
3822                 {"nz",   false, false, false}
3823         },
3824         {
3825                 {"posx", false, false, false},
3826                 {"negx", false, false, false},
3827                 {"posy", false, false, false},
3828                 {"negy", false, false, false},
3829                 {"posz", false, false, false},
3830                 {"negz", false, false, false}
3831         },
3832         {
3833                 {"rt",    true, false,  true},
3834                 {"lf",   false,  true,  true},
3835                 {"ft",    true,  true, false},
3836                 {"bk",   false, false, false},
3837                 {"up",    true, false,  true},
3838                 {"dn",    true, false,  true}
3839         }
3840 };
3841
3842 static int componentorder[4] = {0, 1, 2, 3};
3843
3844 static rtexture_t *R_LoadCubemap(const char *basename)
3845 {
3846         int i, j, cubemapsize;
3847         unsigned char *cubemappixels, *image_buffer;
3848         rtexture_t *cubemaptexture;
3849         char name[256];
3850         // must start 0 so the first loadimagepixels has no requested width/height
3851         cubemapsize = 0;
3852         cubemappixels = NULL;
3853         cubemaptexture = NULL;
3854         // keep trying different suffix groups (posx, px, rt) until one loads
3855         for (j = 0;j < 3 && !cubemappixels;j++)
3856         {
3857                 // load the 6 images in the suffix group
3858                 for (i = 0;i < 6;i++)
3859                 {
3860                         // generate an image name based on the base and and suffix
3861                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3862                         // load it
3863                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3864                         {
3865                                 // an image loaded, make sure width and height are equal
3866                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3867                                 {
3868                                         // if this is the first image to load successfully, allocate the cubemap memory
3869                                         if (!cubemappixels && image_width >= 1)
3870                                         {
3871                                                 cubemapsize = image_width;
3872                                                 // note this clears to black, so unavailable sides are black
3873                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3874                                         }
3875                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3876                                         if (cubemappixels)
3877                                                 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);
3878                                 }
3879                                 else
3880                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3881                                 // free the image
3882                                 Mem_Free(image_buffer);
3883                         }
3884                 }
3885         }
3886         // if a cubemap loaded, upload it
3887         if (cubemappixels)
3888         {
3889                 if (developer_loading.integer)
3890                         Con_Printf("loading cubemap \"%s\"\n", basename);
3891
3892                 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);
3893                 Mem_Free(cubemappixels);
3894         }
3895         else
3896         {
3897                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3898                 if (developer_loading.integer)
3899                 {
3900                         Con_Printf("(tried tried images ");
3901                         for (j = 0;j < 3;j++)
3902                                 for (i = 0;i < 6;i++)
3903                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3904                         Con_Print(" and was unable to find any of them).\n");
3905                 }
3906         }
3907         return cubemaptexture;
3908 }
3909
3910 rtexture_t *R_GetCubemap(const char *basename)
3911 {
3912         int i;
3913         for (i = 0;i < r_texture_numcubemaps;i++)
3914                 if (r_texture_cubemaps[i] != NULL)
3915                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3916                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3917         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3918                 return r_texture_whitecube;
3919         r_texture_numcubemaps++;
3920         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3921         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3922         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3923         return r_texture_cubemaps[i]->texture;
3924 }
3925
3926 static void R_Main_FreeViewCache(void)
3927 {
3928         if (r_refdef.viewcache.entityvisible)
3929                 Mem_Free(r_refdef.viewcache.entityvisible);
3930         if (r_refdef.viewcache.world_pvsbits)
3931                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3932         if (r_refdef.viewcache.world_leafvisible)
3933                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3934         if (r_refdef.viewcache.world_surfacevisible)
3935                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3936         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3937 }
3938
3939 static void R_Main_ResizeViewCache(void)
3940 {
3941         int numentities = r_refdef.scene.numentities;
3942         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3943         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3944         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3945         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3946         if (r_refdef.viewcache.maxentities < numentities)
3947         {
3948                 r_refdef.viewcache.maxentities = numentities;
3949                 if (r_refdef.viewcache.entityvisible)
3950                         Mem_Free(r_refdef.viewcache.entityvisible);
3951                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3952         }
3953         if (r_refdef.viewcache.world_numclusters != numclusters)
3954         {
3955                 r_refdef.viewcache.world_numclusters = numclusters;
3956                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3957                 if (r_refdef.viewcache.world_pvsbits)
3958                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3959                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3960         }
3961         if (r_refdef.viewcache.world_numleafs != numleafs)
3962         {
3963                 r_refdef.viewcache.world_numleafs = numleafs;
3964                 if (r_refdef.viewcache.world_leafvisible)
3965                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3966                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3967         }
3968         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3969         {
3970                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3971                 if (r_refdef.viewcache.world_surfacevisible)
3972                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3973                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3974         }
3975 }
3976
3977 extern rtexture_t *loadingscreentexture;
3978 static void gl_main_start(void)
3979 {
3980         loadingscreentexture = NULL;
3981         r_texture_blanknormalmap = NULL;
3982         r_texture_white = NULL;
3983         r_texture_grey128 = NULL;
3984         r_texture_black = NULL;
3985         r_texture_whitecube = NULL;
3986         r_texture_normalizationcube = NULL;
3987         r_texture_fogattenuation = NULL;
3988         r_texture_fogheighttexture = NULL;
3989         r_texture_gammaramps = NULL;
3990         r_texture_numcubemaps = 0;
3991         r_uniformbufferalignment = 32;
3992
3993         r_loaddds = r_texture_dds_load.integer != 0;
3994         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3995
3996         switch(vid.renderpath)
3997         {
3998         case RENDERPATH_GL20:
3999         case RENDERPATH_D3D9:
4000         case RENDERPATH_D3D10:
4001         case RENDERPATH_D3D11:
4002         case RENDERPATH_SOFT:
4003         case RENDERPATH_GLES2:
4004                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4005                 Cvar_SetValueQuick(&gl_combine, 1);
4006                 Cvar_SetValueQuick(&r_glsl, 1);
4007                 r_loadnormalmap = true;
4008                 r_loadgloss = true;
4009                 r_loadfog = false;
4010                 if (vid.support.arb_uniform_buffer_object)
4011                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4012                 break;
4013         case RENDERPATH_GL13:
4014         case RENDERPATH_GLES1:
4015                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4016                 Cvar_SetValueQuick(&gl_combine, 1);
4017                 Cvar_SetValueQuick(&r_glsl, 0);
4018                 r_loadnormalmap = false;
4019                 r_loadgloss = false;
4020                 r_loadfog = true;
4021                 break;
4022         case RENDERPATH_GL11:
4023                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4024                 Cvar_SetValueQuick(&gl_combine, 0);
4025                 Cvar_SetValueQuick(&r_glsl, 0);
4026                 r_loadnormalmap = false;
4027                 r_loadgloss = false;
4028                 r_loadfog = true;
4029                 break;
4030         }
4031
4032         R_AnimCache_Free();
4033         R_FrameData_Reset();
4034         R_BufferData_Reset();
4035
4036         r_numqueries = 0;
4037         r_maxqueries = 0;
4038         memset(r_queries, 0, sizeof(r_queries));
4039
4040         r_qwskincache = NULL;
4041         r_qwskincache_size = 0;
4042
4043         // due to caching of texture_t references, the collision cache must be reset
4044         Collision_Cache_Reset(true);
4045
4046         // set up r_skinframe loading system for textures
4047         memset(&r_skinframe, 0, sizeof(r_skinframe));
4048         r_skinframe.loadsequence = 1;
4049         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4050
4051         r_main_texturepool = R_AllocTexturePool();
4052         R_BuildBlankTextures();
4053         R_BuildNoTexture();
4054         if (vid.support.arb_texture_cube_map)
4055         {
4056                 R_BuildWhiteCube();
4057                 R_BuildNormalizationCube();
4058         }
4059         r_texture_fogattenuation = NULL;
4060         r_texture_fogheighttexture = NULL;
4061         r_texture_gammaramps = NULL;
4062         //r_texture_fogintensity = NULL;
4063         memset(&r_fb, 0, sizeof(r_fb));
4064         r_glsl_permutation = NULL;
4065         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4066         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4067         glslshaderstring = NULL;
4068 #ifdef SUPPORTD3D
4069         r_hlsl_permutation = NULL;
4070         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4071         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4072 #endif
4073         hlslshaderstring = NULL;
4074         memset(&r_svbsp, 0, sizeof (r_svbsp));
4075
4076         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4077         r_texture_numcubemaps = 0;
4078
4079         r_refdef.fogmasktable_density = 0;
4080 }
4081
4082 static void gl_main_shutdown(void)
4083 {
4084         R_AnimCache_Free();
4085         R_FrameData_Reset();
4086         R_BufferData_Reset();
4087
4088         R_Main_FreeViewCache();
4089
4090         switch(vid.renderpath)
4091         {
4092         case RENDERPATH_GL11:
4093         case RENDERPATH_GL13:
4094         case RENDERPATH_GL20:
4095         case RENDERPATH_GLES1:
4096         case RENDERPATH_GLES2:
4097 #ifdef GL_SAMPLES_PASSED_ARB
4098                 if (r_maxqueries)
4099                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4100 #endif
4101                 break;
4102         case RENDERPATH_D3D9:
4103                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4104                 break;
4105         case RENDERPATH_D3D10:
4106                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4107                 break;
4108         case RENDERPATH_D3D11:
4109                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4110                 break;
4111         case RENDERPATH_SOFT:
4112                 break;
4113         }
4114
4115         r_numqueries = 0;
4116         r_maxqueries = 0;
4117         memset(r_queries, 0, sizeof(r_queries));
4118
4119         r_qwskincache = NULL;
4120         r_qwskincache_size = 0;
4121
4122         // clear out the r_skinframe state
4123         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4124         memset(&r_skinframe, 0, sizeof(r_skinframe));
4125
4126         if (r_svbsp.nodes)
4127                 Mem_Free(r_svbsp.nodes);
4128         memset(&r_svbsp, 0, sizeof (r_svbsp));
4129         R_FreeTexturePool(&r_main_texturepool);
4130         loadingscreentexture = NULL;
4131         r_texture_blanknormalmap = NULL;
4132         r_texture_white = NULL;
4133         r_texture_grey128 = NULL;
4134         r_texture_black = NULL;
4135         r_texture_whitecube = NULL;
4136         r_texture_normalizationcube = NULL;
4137         r_texture_fogattenuation = NULL;
4138         r_texture_fogheighttexture = NULL;
4139         r_texture_gammaramps = NULL;
4140         r_texture_numcubemaps = 0;
4141         //r_texture_fogintensity = NULL;
4142         memset(&r_fb, 0, sizeof(r_fb));
4143         R_GLSL_Restart_f();
4144
4145         r_glsl_permutation = NULL;
4146         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4147         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4148         glslshaderstring = NULL;
4149 #ifdef SUPPORTD3D
4150         r_hlsl_permutation = NULL;
4151         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4152         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4153 #endif
4154         hlslshaderstring = NULL;
4155 }
4156
4157 static void gl_main_newmap(void)
4158 {
4159         // FIXME: move this code to client
4160         char *entities, entname[MAX_QPATH];
4161         if (r_qwskincache)
4162                 Mem_Free(r_qwskincache);
4163         r_qwskincache = NULL;
4164         r_qwskincache_size = 0;
4165         if (cl.worldmodel)
4166         {
4167                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4168                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4169                 {
4170                         CL_ParseEntityLump(entities);
4171                         Mem_Free(entities);
4172                         return;
4173                 }
4174                 if (cl.worldmodel->brush.entities)
4175                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4176         }
4177         R_Main_FreeViewCache();
4178
4179         R_FrameData_Reset();
4180         R_BufferData_Reset();
4181 }
4182
4183 void GL_Main_Init(void)
4184 {
4185         int i;
4186         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4187
4188         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4189         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4190         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4191         if (gamemode == GAME_NEHAHRA)
4192         {
4193                 Cvar_RegisterVariable (&gl_fogenable);
4194                 Cvar_RegisterVariable (&gl_fogdensity);
4195                 Cvar_RegisterVariable (&gl_fogred);
4196                 Cvar_RegisterVariable (&gl_foggreen);
4197                 Cvar_RegisterVariable (&gl_fogblue);
4198                 Cvar_RegisterVariable (&gl_fogstart);
4199                 Cvar_RegisterVariable (&gl_fogend);
4200                 Cvar_RegisterVariable (&gl_skyclip);
4201         }
4202         Cvar_RegisterVariable(&r_motionblur);
4203         Cvar_RegisterVariable(&r_damageblur);
4204         Cvar_RegisterVariable(&r_motionblur_averaging);
4205         Cvar_RegisterVariable(&r_motionblur_randomize);
4206         Cvar_RegisterVariable(&r_motionblur_minblur);
4207         Cvar_RegisterVariable(&r_motionblur_maxblur);
4208         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4209         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4210         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4211         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4212         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4213         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4214         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4215         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4216         Cvar_RegisterVariable(&r_equalize_entities_by);
4217         Cvar_RegisterVariable(&r_equalize_entities_to);
4218         Cvar_RegisterVariable(&r_depthfirst);
4219         Cvar_RegisterVariable(&r_useinfinitefarclip);
4220         Cvar_RegisterVariable(&r_farclip_base);
4221         Cvar_RegisterVariable(&r_farclip_world);
4222         Cvar_RegisterVariable(&r_nearclip);
4223         Cvar_RegisterVariable(&r_deformvertexes);
4224         Cvar_RegisterVariable(&r_transparent);
4225         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4226         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4227         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4228         Cvar_RegisterVariable(&r_showoverdraw);
4229         Cvar_RegisterVariable(&r_showbboxes);
4230         Cvar_RegisterVariable(&r_showsurfaces);
4231         Cvar_RegisterVariable(&r_showtris);
4232         Cvar_RegisterVariable(&r_shownormals);
4233         Cvar_RegisterVariable(&r_showlighting);
4234         Cvar_RegisterVariable(&r_showshadowvolumes);
4235         Cvar_RegisterVariable(&r_showcollisionbrushes);
4236         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4237         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4238         Cvar_RegisterVariable(&r_showdisabledepthtest);
4239         Cvar_RegisterVariable(&r_drawportals);
4240         Cvar_RegisterVariable(&r_drawentities);
4241         Cvar_RegisterVariable(&r_draw2d);
4242         Cvar_RegisterVariable(&r_drawworld);
4243         Cvar_RegisterVariable(&r_cullentities_trace);
4244         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4245         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4246         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4247         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4248         Cvar_RegisterVariable(&r_sortentities);
4249         Cvar_RegisterVariable(&r_drawviewmodel);
4250         Cvar_RegisterVariable(&r_drawexteriormodel);
4251         Cvar_RegisterVariable(&r_speeds);
4252         Cvar_RegisterVariable(&r_fullbrights);
4253         Cvar_RegisterVariable(&r_wateralpha);
4254         Cvar_RegisterVariable(&r_dynamic);
4255         Cvar_RegisterVariable(&r_fakelight);
4256         Cvar_RegisterVariable(&r_fakelight_intensity);
4257         Cvar_RegisterVariable(&r_fullbright);
4258         Cvar_RegisterVariable(&r_shadows);
4259         Cvar_RegisterVariable(&r_shadows_darken);
4260         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4261         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4262         Cvar_RegisterVariable(&r_shadows_throwdistance);
4263         Cvar_RegisterVariable(&r_shadows_throwdirection);
4264         Cvar_RegisterVariable(&r_shadows_focus);
4265         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4266         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4267         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4268         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4269         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4270         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4271         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4272         Cvar_RegisterVariable(&r_fog_exp2);
4273         Cvar_RegisterVariable(&r_fog_clear);
4274         Cvar_RegisterVariable(&r_drawfog);
4275         Cvar_RegisterVariable(&r_transparentdepthmasking);
4276         Cvar_RegisterVariable(&r_transparent_sortmindist);
4277         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4278         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4279         Cvar_RegisterVariable(&r_texture_dds_load);
4280         Cvar_RegisterVariable(&r_texture_dds_save);
4281         Cvar_RegisterVariable(&r_textureunits);
4282         Cvar_RegisterVariable(&gl_combine);
4283         Cvar_RegisterVariable(&r_usedepthtextures);
4284         Cvar_RegisterVariable(&r_viewfbo);
4285         Cvar_RegisterVariable(&r_viewscale);
4286         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4287         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4288         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4289         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4290         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4291         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4292         Cvar_RegisterVariable(&r_glsl);
4293         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4294         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4295         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4296         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4298         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4299         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4300         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4301         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4302         Cvar_RegisterVariable(&r_glsl_postprocess);
4303         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4304         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4311         Cvar_RegisterVariable(&r_celshading);
4312         Cvar_RegisterVariable(&r_celoutlines);
4313
4314         Cvar_RegisterVariable(&r_water);
4315         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4316         Cvar_RegisterVariable(&r_water_clippingplanebias);
4317         Cvar_RegisterVariable(&r_water_refractdistort);
4318         Cvar_RegisterVariable(&r_water_reflectdistort);
4319         Cvar_RegisterVariable(&r_water_scissormode);
4320         Cvar_RegisterVariable(&r_water_lowquality);
4321         Cvar_RegisterVariable(&r_water_hideplayer);
4322         Cvar_RegisterVariable(&r_water_fbo);
4323
4324         Cvar_RegisterVariable(&r_lerpsprites);
4325         Cvar_RegisterVariable(&r_lerpmodels);
4326         Cvar_RegisterVariable(&r_lerplightstyles);
4327         Cvar_RegisterVariable(&r_waterscroll);
4328         Cvar_RegisterVariable(&r_bloom);
4329         Cvar_RegisterVariable(&r_bloom_colorscale);
4330         Cvar_RegisterVariable(&r_bloom_brighten);
4331         Cvar_RegisterVariable(&r_bloom_blur);
4332         Cvar_RegisterVariable(&r_bloom_resolution);
4333         Cvar_RegisterVariable(&r_bloom_colorexponent);
4334         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4335         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4336         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4337         Cvar_RegisterVariable(&r_hdr_glowintensity);
4338         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4339         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4343         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4344         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4345         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4346         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4347         Cvar_RegisterVariable(&developer_texturelogging);
4348         Cvar_RegisterVariable(&gl_lightmaps);
4349         Cvar_RegisterVariable(&r_test);
4350         Cvar_RegisterVariable(&r_batch_multidraw);
4351         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4352         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4353         Cvar_RegisterVariable(&r_glsl_skeletal);
4354         Cvar_RegisterVariable(&r_glsl_saturation);
4355         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4356         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4357         Cvar_RegisterVariable(&r_framedatasize);
4358         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4359                 Cvar_RegisterVariable(&r_bufferdatasize[i]);
4360         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4361         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4362                 Cvar_SetValue("r_fullbrights", 0);
4363         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4364 }
4365
4366 void Render_Init(void)
4367 {
4368         gl_backend_init();
4369         R_Textures_Init();
4370         GL_Main_Init();
4371         Font_Init();
4372         GL_Draw_Init();
4373         R_Shadow_Init();
4374         R_Sky_Init();
4375         GL_Surf_Init();
4376         Sbar_Init();
4377         R_Particles_Init();
4378         R_Explosion_Init();
4379         R_LightningBeams_Init();
4380         Mod_RenderInit();
4381 }
4382
4383 /*
4384 ===============
4385 GL_Init
4386 ===============
4387 */
4388 #ifndef USE_GLES2
4389 extern char *ENGINE_EXTENSIONS;
4390 void GL_Init (void)
4391 {
4392         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4393         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4394         gl_version = (const char *)qglGetString(GL_VERSION);
4395         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4396
4397         if (!gl_extensions)
4398                 gl_extensions = "";
4399         if (!gl_platformextensions)
4400                 gl_platformextensions = "";
4401
4402         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4403         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4404         Con_Printf("GL_VERSION: %s\n", gl_version);
4405         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4406         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4407
4408         VID_CheckExtensions();
4409
4410         // LordHavoc: report supported extensions
4411         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4412
4413         // clear to black (loading plaque will be seen over this)
4414         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4415 }
4416 #endif
4417
4418 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4419 {
4420         int i;
4421         mplane_t *p;
4422         if (r_trippy.integer)
4423                 return false;
4424         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4425         {
4426                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4427                 if (i == 4)
4428                         continue;
4429                 p = r_refdef.view.frustum + i;
4430                 switch(p->signbits)
4431                 {
4432                 default:
4433                 case 0:
4434                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 1:
4438                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 2:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 3:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 4:
4450                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 5:
4454                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 6:
4458                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 case 7:
4462                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4463                                 return true;
4464                         break;
4465                 }
4466         }
4467         return false;
4468 }
4469
4470 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4471 {
4472         int i;
4473         const mplane_t *p;
4474         if (r_trippy.integer)
4475                 return false;
4476         for (i = 0;i < numplanes;i++)
4477         {
4478                 p = planes + i;
4479                 switch(p->signbits)
4480                 {
4481                 default:
4482                 case 0:
4483                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 1:
4487                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 2:
4491                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 3:
4495                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 4:
4499                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 case 5:
4503                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4504                                 return true;
4505                         break;
4506                 case 6:
4507                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4508                                 return true;
4509                         break;
4510                 case 7:
4511                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4512                                 return true;
4513                         break;
4514                 }
4515         }
4516         return false;
4517 }
4518
4519 //==================================================================================
4520
4521 // LordHavoc: this stores temporary data used within the same frame
4522
4523 typedef struct r_framedata_mem_s
4524 {
4525         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4526         size_t size; // how much usable space
4527         size_t current; // how much space in use
4528         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4529         size_t wantedsize; // how much space was allocated
4530         unsigned char *data; // start of real data (16byte aligned)
4531 }
4532 r_framedata_mem_t;
4533
4534 static r_framedata_mem_t *r_framedata_mem;
4535
4536 void R_FrameData_Reset(void)
4537 {
4538         while (r_framedata_mem)
4539         {
4540                 r_framedata_mem_t *next = r_framedata_mem->purge;
4541                 Mem_Free(r_framedata_mem);
4542                 r_framedata_mem = next;
4543         }
4544 }
4545
4546 static void R_FrameData_Resize(qboolean mustgrow)
4547 {
4548         size_t wantedsize;
4549         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4550         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4551         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4552         {
4553                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4554                 newmem->wantedsize = wantedsize;
4555                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4556                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4557                 newmem->current = 0;
4558                 newmem->mark = 0;
4559                 newmem->purge = r_framedata_mem;
4560                 r_framedata_mem = newmem;
4561         }
4562 }
4563
4564 void R_FrameData_NewFrame(void)
4565 {
4566         R_FrameData_Resize(false);
4567         if (!r_framedata_mem)
4568                 return;
4569         // if we ran out of space on the last frame, free the old memory now
4570         while (r_framedata_mem->purge)
4571         {
4572                 // repeatedly remove the second item in the list, leaving only head
4573                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4574                 Mem_Free(r_framedata_mem->purge);
4575                 r_framedata_mem->purge = next;
4576         }
4577         // reset the current mem pointer
4578         r_framedata_mem->current = 0;
4579         r_framedata_mem->mark = 0;
4580 }
4581
4582 void *R_FrameData_Alloc(size_t size)
4583 {
4584         void *data;
4585         float newvalue;
4586
4587         // align to 16 byte boundary - the data pointer is already aligned, so we
4588         // only need to ensure the size of every allocation is also aligned
4589         size = (size + 15) & ~15;
4590
4591         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4592         {
4593                 // emergency - we ran out of space, allocate more memory
4594                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4595                 // this might not be a growing it, but we'll allocate another buffer every time
4596                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4597                 R_FrameData_Resize(true);
4598         }
4599
4600         data = r_framedata_mem->data + r_framedata_mem->current;
4601         r_framedata_mem->current += size;
4602
4603         // count the usage for stats
4604         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4605         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4606
4607         return (void *)data;
4608 }
4609
4610 void *R_FrameData_Store(size_t size, void *data)
4611 {
4612         void *d = R_FrameData_Alloc(size);
4613         if (d && data)
4614                 memcpy(d, data, size);
4615         return d;
4616 }
4617
4618 void R_FrameData_SetMark(void)
4619 {
4620         if (!r_framedata_mem)
4621                 return;
4622         r_framedata_mem->mark = r_framedata_mem->current;
4623 }
4624
4625 void R_FrameData_ReturnToMark(void)
4626 {
4627         if (!r_framedata_mem)
4628                 return;
4629         r_framedata_mem->current = r_framedata_mem->mark;
4630 }
4631
4632 //==================================================================================
4633
4634 // avoid reusing the same buffer objects on consecutive buffers
4635 #define R_BUFFERDATA_CYCLE 2
4636
4637 typedef struct r_bufferdata_buffer_s
4638 {
4639         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4640         size_t size; // how much usable space
4641         size_t current; // how much space in use
4642         r_meshbuffer_t *buffer; // the buffer itself
4643 }
4644 r_bufferdata_buffer_t;
4645
4646 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4647 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4648
4649 /// frees all dynamic buffers
4650 void R_BufferData_Reset(void)
4651 {
4652         int cycle, type;
4653         r_bufferdata_buffer_t **p, *mem;
4654         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4655         {
4656                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4657                 {
4658                         // free all buffers
4659                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type];
4660                         while (*p)
4661                         {
4662                                 mem = *p;
4663                                 *p = (*p)->purge;
4664                                 if (mem->buffer)
4665                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4666                                 Mem_Free(mem);
4667                         }
4668                 }
4669         }
4670 }
4671
4672 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4673 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow)
4674 {
4675         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4676         size_t size;
4677         size = (size_t)(r_bufferdatasize[type].value * 1024*1024);
4678         size = bound(65536, size, 512*1024*1024);
4679         if (!mem || mem->size != size || mustgrow)
4680         {
4681                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4682                 mem->size = size;
4683                 mem->current = 0;
4684                 if (type == R_BUFFERDATA_VERTEX)
4685                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4686                 else if (type == R_BUFFERDATA_INDEX16)
4687                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4688                 else if (type == R_BUFFERDATA_INDEX32)
4689                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4690                 else if (type == R_BUFFERDATA_UNIFORM)
4691                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4692                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4693                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4694         }
4695 }
4696
4697 void R_BufferData_NewFrame(void)
4698 {
4699         int type;
4700         r_bufferdata_buffer_t **p, *mem;
4701         // cycle to the next frame's buffers
4702         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4703         // if we ran out of space on the last time we used these buffers, free the old memory now
4704         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4705         {
4706                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4707                 {
4708                         R_BufferData_Resize((r_bufferdata_type_t)type, false);
4709                         // free all but the head buffer, this is how we recycle obsolete
4710                         // buffers after they are no longer in use
4711                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4712                         while (*p)
4713                         {
4714                                 mem = *p;
4715                                 *p = (*p)->purge;
4716                                 if (mem->buffer)
4717                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4718                                 Mem_Free(mem);
4719                         }
4720                         // reset the current offset
4721                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4722                 }
4723         }
4724 }
4725
4726 r_meshbuffer_t *R_BufferData_Store(size_t datasize, void *data, r_bufferdata_type_t type, int *returnbufferoffset, qboolean allowfail)
4727 {
4728         r_bufferdata_buffer_t *mem;
4729         int offset = 0;
4730         int padsize;
4731         float newvalue;
4732
4733         *returnbufferoffset = 0;
4734
4735         // align size to a byte boundary appropriate for the buffer type, this
4736         // makes all allocations have aligned start offsets
4737         if (type == R_BUFFERDATA_UNIFORM)
4738                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4739         else
4740                 padsize = (datasize + 15) & ~15;
4741
4742         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)
4743         {
4744                 // emergency - we ran out of space, allocate more memory
4745                 newvalue = bound(0.25f, r_bufferdatasize[type].value * 2.0f, 256.0f);
4746                 // if we're already at the limit, just fail (if allowfail is false we might run out of video ram)
4747                 if (newvalue == r_bufferdatasize[type].value && allowfail)
4748                         return NULL;
4749                 Cvar_SetValueQuick(&r_bufferdatasize[type], newvalue);
4750                 R_BufferData_Resize(type, true);
4751         }
4752
4753         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4754         offset = mem->current;
4755         mem->current += padsize;
4756
4757         // upload the data to the buffer at the chosen offset
4758         if (offset == 0)
4759                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4760         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4761
4762         // count the usage for stats
4763         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4764         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4765
4766         // return the buffer offset
4767         *returnbufferoffset = offset;
4768
4769         return mem->buffer;
4770 }
4771
4772 //==================================================================================
4773
4774 // LordHavoc: animcache originally written by Echon, rewritten since then
4775
4776 /**
4777  * Animation cache prevents re-generating mesh data for an animated model
4778  * multiple times in one frame for lighting, shadowing, reflections, etc.
4779  */
4780
4781 void R_AnimCache_Free(void)
4782 {
4783 }
4784
4785 void R_AnimCache_ClearCache(void)
4786 {
4787         int i;
4788         entity_render_t *ent;
4789
4790         for (i = 0;i < r_refdef.scene.numentities;i++)
4791         {
4792                 ent = r_refdef.scene.entities[i];
4793                 ent->animcache_vertex3f = NULL;
4794                 ent->animcache_vertex3f_vertexbuffer = NULL;
4795                 ent->animcache_vertex3f_bufferoffset = 0;
4796                 ent->animcache_normal3f = NULL;
4797                 ent->animcache_normal3f_vertexbuffer = NULL;
4798                 ent->animcache_normal3f_bufferoffset = 0;
4799                 ent->animcache_svector3f = NULL;
4800                 ent->animcache_svector3f_vertexbuffer = NULL;
4801                 ent->animcache_svector3f_bufferoffset = 0;
4802                 ent->animcache_tvector3f = NULL;
4803                 ent->animcache_tvector3f_vertexbuffer = NULL;
4804                 ent->animcache_tvector3f_bufferoffset = 0;
4805                 ent->animcache_vertexmesh = NULL;
4806                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4807                 ent->animcache_vertexmesh_bufferoffset = 0;
4808                 ent->animcache_skeletaltransform3x4 = NULL;
4809                 ent->animcache_skeletaltransform3x4buffer = NULL;
4810                 ent->animcache_skeletaltransform3x4offset = 0;
4811                 ent->animcache_skeletaltransform3x4size = 0;
4812         }
4813 }
4814
4815 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4816 {
4817         int i;
4818
4819         // check if we need the meshbuffers
4820         if (!vid.useinterleavedarrays)
4821                 return;
4822
4823         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4824                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4825         // TODO: upload vertexbuffer?
4826         if (ent->animcache_vertexmesh)
4827         {
4828                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4829                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4830                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4831                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4832                 for (i = 0;i < numvertices;i++)
4833                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4834                 if (ent->animcache_svector3f)
4835                         for (i = 0;i < numvertices;i++)
4836                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4837                 if (ent->animcache_tvector3f)
4838                         for (i = 0;i < numvertices;i++)
4839                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4840                 if (ent->animcache_normal3f)
4841                         for (i = 0;i < numvertices;i++)
4842                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4843         }
4844 }
4845
4846 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4847 {
4848         dp_model_t *model = ent->model;
4849         int numvertices;
4850
4851         // see if this ent is worth caching
4852         if (!model || !model->Draw || !model->AnimateVertices)
4853                 return false;
4854         // nothing to cache if it contains no animations and has no skeleton
4855         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4856                 return false;
4857         // see if it is already cached for gpuskeletal
4858         if (ent->animcache_skeletaltransform3x4)
4859                 return false;
4860         // see if it is already cached as a mesh
4861         if (ent->animcache_vertex3f)
4862         {
4863                 // check if we need to add normals or tangents
4864                 if (ent->animcache_normal3f)
4865                         wantnormals = false;
4866                 if (ent->animcache_svector3f)
4867                         wanttangents = false;
4868                 if (!wantnormals && !wanttangents)
4869                         return false;
4870         }
4871
4872         // check which kind of cache we need to generate
4873         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4874         {
4875                 // cache the skeleton so the vertex shader can use it
4876                 int i;
4877                 int blends;
4878                 const skeleton_t *skeleton = ent->skeleton;
4879                 const frameblend_t *frameblend = ent->frameblend;
4880                 float *boneposerelative;
4881                 float m[12];
4882                 static float bonepose[256][12];
4883                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4884                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4885                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4886                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4887                 boneposerelative = ent->animcache_skeletaltransform3x4;
4888                 if (skeleton && !skeleton->relativetransforms)
4889                         skeleton = NULL;
4890                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4891                 if (skeleton)
4892                 {
4893                         for (i = 0;i < model->num_bones;i++)
4894                         {
4895                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4896                                 if (model->data_bones[i].parent >= 0)
4897                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4898                                 else
4899                                         memcpy(bonepose[i], m, sizeof(m));
4900
4901                                 // create a relative deformation matrix to describe displacement
4902                                 // from the base mesh, which is used by the actual weighting
4903                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4904                         }
4905                 }
4906                 else
4907                 {
4908                         for (i = 0;i < model->num_bones;i++)
4909                         {
4910                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4911                                 float lerp = frameblend[0].lerp,
4912                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4913                                         rx = pose7s[3] * lerp,
4914                                         ry = pose7s[4] * lerp,
4915                                         rz = pose7s[5] * lerp,
4916                                         rw = pose7s[6] * lerp,
4917                                         dx = tx*rw + ty*rz - tz*ry,
4918                                         dy = -tx*rz + ty*rw + tz*rx,
4919                                         dz = tx*ry - ty*rx + tz*rw,
4920                                         dw = -tx*rx - ty*ry - tz*rz,
4921                                         scale, sx, sy, sz, sw;
4922                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4923                                 {
4924                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4925                                         float lerp = frameblend[blends].lerp,
4926                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4927                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4928                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4929                                         qx *= lerp;
4930                                         qy *= lerp;
4931                                         qz *= lerp;
4932                                         qw *= lerp;
4933                                         rx += qx;
4934                                         ry += qy;
4935                                         rz += qz;
4936                                         rw += qw;
4937                                         dx += tx*qw + ty*qz - tz*qy;
4938                                         dy += -tx*qz + ty*qw + tz*qx;
4939                                         dz += tx*qy - ty*qx + tz*qw;
4940                                         dw += -tx*qx - ty*qy - tz*qz;
4941                                 }
4942                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4943                                 sx = rx * scale;
4944                                 sy = ry * scale;
4945                                 sz = rz * scale;
4946                                 sw = rw * scale;
4947                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4948                                 m[1] = 2*(sx*ry - sw*rz);
4949                                 m[2] = 2*(sx*rz + sw*ry);
4950                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4951                                 m[4] = 2*(sx*ry + sw*rz);
4952                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4953                                 m[6] = 2*(sy*rz - sw*rx);
4954                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4955                                 m[8] = 2*(sx*rz - sw*ry);
4956                                 m[9] = 2*(sy*rz + sw*rx);
4957                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4958                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4959                                 if (i == r_skeletal_debugbone.integer)
4960                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4961                                 m[3] *= r_skeletal_debugtranslatex.value;
4962                                 m[7] *= r_skeletal_debugtranslatey.value;
4963                                 m[11] *= r_skeletal_debugtranslatez.value;
4964                                 if (model->data_bones[i].parent >= 0)
4965                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4966                                 else
4967                                         memcpy(bonepose[i], m, sizeof(m));
4968                                 // create a relative deformation matrix to describe displacement
4969                                 // from the base mesh, which is used by the actual weighting
4970                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4971                         }
4972                 }
4973                 // note: this can fail if the buffer is at the grow limit
4974                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4975                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset, true);
4976         }
4977         else if (ent->animcache_vertex3f)
4978         {
4979                 // mesh was already cached but we may need to add normals/tangents
4980                 // (this only happens with multiple views, reflections, cameras, etc)
4981                 if (wantnormals || wanttangents)
4982                 {
4983                         numvertices = model->surfmesh.num_vertices;
4984                         if (wantnormals)
4985                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4986                         if (wanttangents)
4987                         {
4988                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4989                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4990                         }
4991                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4992                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4993                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4994                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4995                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4996                 }
4997         }
4998         else
4999         {
5000                 // generate mesh cache
5001                 numvertices = model->surfmesh.num_vertices;
5002                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5003                 if (wantnormals)
5004                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5005                 if (wanttangents)
5006                 {
5007                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5008                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5009                 }
5010                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5011                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5012                 if (wantnormals || wanttangents)
5013                 {
5014                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5015                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5016                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5017                 }
5018                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5019                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5020                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5021         }
5022         return true;
5023 }
5024
5025 void R_AnimCache_CacheVisibleEntities(void)
5026 {
5027         int i;
5028         qboolean wantnormals = true;
5029         qboolean wanttangents = !r_showsurfaces.integer;
5030
5031         switch(vid.renderpath)
5032         {
5033         case RENDERPATH_GL20:
5034         case RENDERPATH_D3D9:
5035         case RENDERPATH_D3D10:
5036         case RENDERPATH_D3D11:
5037         case RENDERPATH_GLES2:
5038                 break;
5039         case RENDERPATH_GL11:
5040         case RENDERPATH_GL13:
5041         case RENDERPATH_GLES1:
5042                 wanttangents = false;
5043                 break;
5044         case RENDERPATH_SOFT:
5045                 break;
5046         }
5047
5048         if (r_shownormals.integer)
5049                 wanttangents = wantnormals = true;
5050
5051         // TODO: thread this
5052         // NOTE: R_PrepareRTLights() also caches entities
5053
5054         for (i = 0;i < r_refdef.scene.numentities;i++)
5055                 if (r_refdef.viewcache.entityvisible[i])
5056                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5057 }
5058
5059 //==================================================================================
5060
5061 extern cvar_t r_overheadsprites_pushback;
5062
5063 static void R_View_UpdateEntityLighting (void)
5064 {
5065         int i;
5066         entity_render_t *ent;
5067         vec3_t tempdiffusenormal, avg;
5068         vec_t f, fa, fd, fdd;
5069         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5070
5071         for (i = 0;i < r_refdef.scene.numentities;i++)
5072         {
5073                 ent = r_refdef.scene.entities[i];
5074
5075                 // skip unseen models
5076                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5077                         continue;
5078
5079                 // skip bsp models
5080                 if (ent->model && ent->model == cl.worldmodel)
5081                 {
5082                         // TODO: use modellight for r_ambient settings on world?
5083                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5084                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5085                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5086                         continue;
5087                 }
5088                 
5089                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5090                 {
5091                         // aleady updated by CSQC
5092                         // TODO: force modellight on BSP models in this case?
5093                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5094                 }
5095                 else
5096                 {
5097                         // fetch the lighting from the worldmodel data
5098                         VectorClear(ent->modellight_ambient);
5099                         VectorClear(ent->modellight_diffuse);
5100                         VectorClear(tempdiffusenormal);
5101                         if (ent->flags & RENDER_LIGHT)
5102                         {
5103                                 vec3_t org;
5104                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5105
5106                                 // complete lightning for lit sprites
5107                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5108                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5109                                 {
5110                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5111                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5112                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5113                                 }
5114                                 else
5115                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5116
5117                                 if(ent->flags & RENDER_EQUALIZE)
5118                                 {
5119                                         // first fix up ambient lighting...
5120                                         if(r_equalize_entities_minambient.value > 0)
5121                                         {
5122                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5123                                                 if(fd > 0)
5124                                                 {
5125                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5126                                                         if(fa < r_equalize_entities_minambient.value * fd)
5127                                                         {
5128                                                                 // solve:
5129                                                                 //   fa'/fd' = minambient
5130                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5131                                                                 //   ...
5132                                                                 //   fa' = fd' * minambient
5133                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5134                                                                 //   ...
5135                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5136                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5137                                                                 //   ...
5138                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5139                                                                 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
5140                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5141                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5142                                                         }
5143                                                 }
5144                                         }
5145
5146                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5147                                         {
5148                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5149                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5150                                                 f = fa + 0.25 * fd;
5151                                                 if(f > 0)
5152                                                 {
5153                                                         // adjust brightness and saturation to target
5154                                                         avg[0] = avg[1] = avg[2] = fa / f;
5155                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5156                                                         avg[0] = avg[1] = avg[2] = fd / f;
5157                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5158                                                 }
5159                                         }
5160                                 }
5161                         }
5162                         else // highly rare
5163                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5164                 }
5165
5166                 // move the light direction into modelspace coordinates for lighting code
5167                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5168                 if(VectorLength2(ent->modellight_lightdir) == 0)
5169                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5170                 VectorNormalize(ent->modellight_lightdir);
5171         }
5172 }
5173
5174 #define MAX_LINEOFSIGHTTRACES 64
5175
5176 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5177 {
5178         int i;
5179         vec3_t boxmins, boxmaxs;
5180         vec3_t start;
5181         vec3_t end;
5182         dp_model_t *model = r_refdef.scene.worldmodel;
5183
5184         if (!model || !model->brush.TraceLineOfSight)
5185                 return true;
5186
5187         // expand the box a little
5188         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5189         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5190         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5191         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5192         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5193         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5194
5195         // return true if eye is inside enlarged box
5196         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5197                 return true;
5198
5199         // try center
5200         VectorCopy(eye, start);
5201         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5202         if (model->brush.TraceLineOfSight(model, start, end))
5203                 return true;
5204
5205         // try various random positions
5206         for (i = 0;i < numsamples;i++)
5207         {
5208                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5209                 if (model->brush.TraceLineOfSight(model, start, end))
5210                         return true;
5211         }
5212
5213         return false;
5214 }
5215
5216
5217 static void R_View_UpdateEntityVisible (void)
5218 {
5219         int i;
5220         int renderimask;
5221         int samples;
5222         entity_render_t *ent;
5223
5224         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5225                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5226                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5227                 :                                                          RENDER_EXTERIORMODEL;
5228         if (!r_drawviewmodel.integer)
5229                 renderimask |= RENDER_VIEWMODEL;
5230         if (!r_drawexteriormodel.integer)
5231                 renderimask |= RENDER_EXTERIORMODEL;
5232         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5233         {
5234                 // worldmodel can check visibility
5235                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5236                 for (i = 0;i < r_refdef.scene.numentities;i++)
5237                 {
5238                         ent = r_refdef.scene.entities[i];
5239                         if (!(ent->flags & renderimask))
5240                         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)))
5241                         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))
5242                                 r_refdef.viewcache.entityvisible[i] = true;
5243                 }
5244         }
5245         else
5246         {
5247                 // no worldmodel or it can't check visibility
5248                 for (i = 0;i < r_refdef.scene.numentities;i++)
5249                 {
5250                         ent = r_refdef.scene.entities[i];
5251                         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));
5252                 }
5253         }
5254         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5255                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5256         {
5257                 for (i = 0;i < r_refdef.scene.numentities;i++)
5258                 {
5259                         if (!r_refdef.viewcache.entityvisible[i])
5260                                 continue;
5261                         ent = r_refdef.scene.entities[i];
5262                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5263                         {
5264                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5265                                 if (samples < 0)
5266                                         continue; // temp entities do pvs only
5267                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5268                                         ent->last_trace_visibility = realtime;
5269                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5270                                         r_refdef.viewcache.entityvisible[i] = 0;
5271                         }
5272                 }
5273         }
5274 }
5275
5276 /// only used if skyrendermasked, and normally returns false
5277 static int R_DrawBrushModelsSky (void)
5278 {
5279         int i, sky;
5280         entity_render_t *ent;
5281
5282         sky = false;
5283         for (i = 0;i < r_refdef.scene.numentities;i++)
5284         {
5285                 if (!r_refdef.viewcache.entityvisible[i])
5286                         continue;
5287                 ent = r_refdef.scene.entities[i];
5288                 if (!ent->model || !ent->model->DrawSky)
5289                         continue;
5290                 ent->model->DrawSky(ent);
5291                 sky = true;
5292         }
5293         return sky;
5294 }
5295
5296 static void R_DrawNoModel(entity_render_t *ent);
5297 static void R_DrawModels(void)
5298 {
5299         int i;
5300         entity_render_t *ent;
5301
5302         for (i = 0;i < r_refdef.scene.numentities;i++)
5303         {
5304                 if (!r_refdef.viewcache.entityvisible[i])
5305                         continue;
5306                 ent = r_refdef.scene.entities[i];
5307                 r_refdef.stats[r_stat_entities]++;
5308                 /*
5309                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5310                 {
5311                         vec3_t f, l, u, o;
5312                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5313                         Con_Printf("R_DrawModels\n");
5314                         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]);
5315                         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);
5316                         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);
5317                 }
5318                 */
5319                 if (ent->model && ent->model->Draw != NULL)
5320                         ent->model->Draw(ent);
5321                 else
5322                         R_DrawNoModel(ent);
5323         }
5324 }
5325
5326 static void R_DrawModelsDepth(void)
5327 {
5328         int i;
5329         entity_render_t *ent;
5330
5331         for (i = 0;i < r_refdef.scene.numentities;i++)
5332         {
5333                 if (!r_refdef.viewcache.entityvisible[i])
5334                         continue;
5335                 ent = r_refdef.scene.entities[i];
5336                 if (ent->model && ent->model->DrawDepth != NULL)
5337                         ent->model->DrawDepth(ent);
5338         }
5339 }
5340
5341 static void R_DrawModelsDebug(void)
5342 {
5343         int i;
5344         entity_render_t *ent;
5345
5346         for (i = 0;i < r_refdef.scene.numentities;i++)
5347         {
5348                 if (!r_refdef.viewcache.entityvisible[i])
5349                         continue;
5350                 ent = r_refdef.scene.entities[i];
5351                 if (ent->model && ent->model->DrawDebug != NULL)
5352                         ent->model->DrawDebug(ent);
5353         }
5354 }
5355
5356 static void R_DrawModelsAddWaterPlanes(void)
5357 {
5358         int i;
5359         entity_render_t *ent;
5360
5361         for (i = 0;i < r_refdef.scene.numentities;i++)
5362         {
5363                 if (!r_refdef.viewcache.entityvisible[i])
5364                         continue;
5365                 ent = r_refdef.scene.entities[i];
5366                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5367                         ent->model->DrawAddWaterPlanes(ent);
5368         }
5369 }
5370
5371 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}};
5372
5373 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5374 {
5375         if (r_hdr_irisadaptation.integer)
5376         {
5377                 vec3_t p;
5378                 vec3_t ambient;
5379                 vec3_t diffuse;
5380                 vec3_t diffusenormal;
5381                 vec3_t forward;
5382                 vec_t brightness = 0.0f;
5383                 vec_t goal;
5384                 vec_t current;
5385                 vec_t d;
5386                 int c;
5387                 VectorCopy(r_refdef.view.forward, forward);
5388                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5389                 {
5390                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5391                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5392                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5393                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5394                         d = DotProduct(forward, diffusenormal);
5395                         brightness += VectorLength(ambient);
5396                         if (d > 0)
5397                                 brightness += d * VectorLength(diffuse);
5398                 }
5399                 brightness *= 1.0f / c;
5400                 brightness += 0.00001f; // make sure it's never zero
5401                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5402                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5403                 current = r_hdr_irisadaptation_value.value;
5404                 if (current < goal)
5405                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5406                 else if (current > goal)
5407                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5408                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5409                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5410         }
5411         else if (r_hdr_irisadaptation_value.value != 1.0f)
5412                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5413 }
5414
5415 static void R_View_SetFrustum(const int *scissor)
5416 {
5417         int i;
5418         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5419         vec3_t forward, left, up, origin, v;
5420
5421         if(scissor)
5422         {
5423                 // flipped x coordinates (because x points left here)
5424                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5425                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5426
5427                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5428                 switch(vid.renderpath)
5429                 {
5430                         case RENDERPATH_D3D9:
5431                         case RENDERPATH_D3D10:
5432                         case RENDERPATH_D3D11:
5433                                 // non-flipped y coordinates
5434                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5435                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5436                                 break;
5437                         case RENDERPATH_SOFT:
5438                         case RENDERPATH_GL11:
5439                         case RENDERPATH_GL13:
5440                         case RENDERPATH_GL20:
5441                         case RENDERPATH_GLES1:
5442                         case RENDERPATH_GLES2:
5443                                 // non-flipped y coordinates
5444                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5445                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5446                                 break;
5447                 }
5448         }
5449
5450         // we can't trust r_refdef.view.forward and friends in reflected scenes
5451         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5452
5453 #if 0
5454         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5455         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5456         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5457         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5458         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5459         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5460         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5461         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5462         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5463         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5464         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5465         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5466 #endif
5467
5468 #if 0
5469         zNear = r_refdef.nearclip;
5470         nudge = 1.0 - 1.0 / (1<<23);
5471         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5472         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5473         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5474         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5475         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5476         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5477         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5478         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5479 #endif
5480
5481
5482
5483 #if 0
5484         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5485         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5486         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5487         r_refdef.view.frustum[0].dist = m[15] - m[12];
5488
5489         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5490         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5491         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5492         r_refdef.view.frustum[1].dist = m[15] + m[12];
5493
5494         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5495         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5496         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5497         r_refdef.view.frustum[2].dist = m[15] - m[13];
5498
5499         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5500         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5501         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5502         r_refdef.view.frustum[3].dist = m[15] + m[13];
5503
5504         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5505         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5506         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5507         r_refdef.view.frustum[4].dist = m[15] - m[14];
5508
5509         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5510         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5511         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5512         r_refdef.view.frustum[5].dist = m[15] + m[14];
5513 #endif
5514
5515         if (r_refdef.view.useperspective)
5516         {
5517                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5518                 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]);
5519                 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]);
5520                 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]);
5521                 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]);
5522
5523                 // then the normals from the corners relative to origin
5524                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5525                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5526                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5527                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5528
5529                 // in a NORMAL view, forward cross left == up
5530                 // in a REFLECTED view, forward cross left == down
5531                 // so our cross products above need to be adjusted for a left handed coordinate system
5532                 CrossProduct(forward, left, v);
5533                 if(DotProduct(v, up) < 0)
5534                 {
5535                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5536                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5537                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5538                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5539                 }
5540
5541                 // Leaving those out was a mistake, those were in the old code, and they
5542                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5543                 // I couldn't reproduce it after adding those normalizations. --blub
5544                 VectorNormalize(r_refdef.view.frustum[0].normal);
5545                 VectorNormalize(r_refdef.view.frustum[1].normal);
5546                 VectorNormalize(r_refdef.view.frustum[2].normal);
5547                 VectorNormalize(r_refdef.view.frustum[3].normal);
5548
5549                 // make the corners absolute
5550                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5551                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5552                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5553                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5554
5555                 // one more normal
5556                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5557
5558                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5559                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5560                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5561                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5562                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5563         }
5564         else
5565         {
5566                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5567                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5568                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5569                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5570                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5571                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5572                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5573                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5574                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5575                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5576         }
5577         r_refdef.view.numfrustumplanes = 5;
5578
5579         if (r_refdef.view.useclipplane)
5580         {
5581                 r_refdef.view.numfrustumplanes = 6;
5582                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5583         }
5584
5585         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5586                 PlaneClassify(r_refdef.view.frustum + i);
5587
5588         // LordHavoc: note to all quake engine coders, Quake had a special case
5589         // for 90 degrees which assumed a square view (wrong), so I removed it,
5590         // Quake2 has it disabled as well.
5591
5592         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5593         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5594         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5595         //PlaneClassify(&frustum[0]);
5596
5597         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5598         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5599         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5600         //PlaneClassify(&frustum[1]);
5601
5602         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5603         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5604         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5605         //PlaneClassify(&frustum[2]);
5606
5607         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5608         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5609         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5610         //PlaneClassify(&frustum[3]);
5611
5612         // nearclip plane
5613         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5614         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5615         //PlaneClassify(&frustum[4]);
5616 }
5617
5618 static void R_View_UpdateWithScissor(const int *myscissor)
5619 {
5620         R_Main_ResizeViewCache();
5621         R_View_SetFrustum(myscissor);
5622         R_View_WorldVisibility(r_refdef.view.useclipplane);
5623         R_View_UpdateEntityVisible();
5624         R_View_UpdateEntityLighting();
5625 }
5626
5627 static void R_View_Update(void)
5628 {
5629         R_Main_ResizeViewCache();
5630         R_View_SetFrustum(NULL);
5631         R_View_WorldVisibility(r_refdef.view.useclipplane);
5632         R_View_UpdateEntityVisible();
5633         R_View_UpdateEntityLighting();
5634 }
5635
5636 float viewscalefpsadjusted = 1.0f;
5637
5638 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5639 {
5640         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5641         scale = bound(0.03125f, scale, 1.0f);
5642         *outwidth = (int)ceil(width * scale);
5643         *outheight = (int)ceil(height * scale);
5644 }
5645
5646 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5647 {
5648         const float *customclipplane = NULL;
5649         float plane[4];
5650         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5651         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5652         {
5653                 // LordHavoc: couldn't figure out how to make this approach the
5654                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5655                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5656                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5657                         dist = r_refdef.view.clipplane.dist;
5658                 plane[0] = r_refdef.view.clipplane.normal[0];
5659                 plane[1] = r_refdef.view.clipplane.normal[1];
5660                 plane[2] = r_refdef.view.clipplane.normal[2];
5661                 plane[3] = -dist;
5662                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5663         }
5664
5665         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5666         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5667
5668         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5669         if (!r_refdef.view.useperspective)
5670                 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);
5671         else if (vid.stencil && r_useinfinitefarclip.integer)
5672                 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);
5673         else
5674                 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);
5675         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5676         R_SetViewport(&r_refdef.view.viewport);
5677         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5678         {
5679                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5680                 float screenplane[4];
5681                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5682                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5683                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5684                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5685                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5686         }
5687 }
5688
5689 void R_EntityMatrix(const matrix4x4_t *matrix)
5690 {
5691         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5692         {
5693                 gl_modelmatrixchanged = false;
5694                 gl_modelmatrix = *matrix;
5695                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5696                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5697                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5698                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5699                 CHECKGLERROR
5700                 switch(vid.renderpath)
5701                 {
5702                 case RENDERPATH_D3D9:
5703 #ifdef SUPPORTD3D
5704                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5705                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5706 #endif
5707                         break;
5708                 case RENDERPATH_D3D10:
5709                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5710                         break;
5711                 case RENDERPATH_D3D11:
5712                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5713                         break;
5714                 case RENDERPATH_GL11:
5715                 case RENDERPATH_GL13:
5716                 case RENDERPATH_GLES1:
5717                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5718                         break;
5719                 case RENDERPATH_SOFT:
5720                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5721                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5722                         break;
5723                 case RENDERPATH_GL20:
5724                 case RENDERPATH_GLES2:
5725                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5726                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5727                         break;
5728                 }
5729         }
5730 }
5731
5732 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5733 {
5734         r_viewport_t viewport;
5735
5736         CHECKGLERROR
5737
5738         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5739         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);
5740         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5741         R_SetViewport(&viewport);
5742         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5743         GL_Color(1, 1, 1, 1);
5744         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5745         GL_BlendFunc(GL_ONE, GL_ZERO);
5746         GL_ScissorTest(false);
5747         GL_DepthMask(false);
5748         GL_DepthRange(0, 1);
5749         GL_DepthTest(false);
5750         GL_DepthFunc(GL_LEQUAL);
5751         R_EntityMatrix(&identitymatrix);
5752         R_Mesh_ResetTextureState();
5753         GL_PolygonOffset(0, 0);
5754         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5755         switch(vid.renderpath)
5756         {
5757         case RENDERPATH_GL11:
5758         case RENDERPATH_GL13:
5759         case RENDERPATH_GL20:
5760         case RENDERPATH_GLES1:
5761         case RENDERPATH_GLES2:
5762                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5763                 break;
5764         case RENDERPATH_D3D9:
5765         case RENDERPATH_D3D10:
5766         case RENDERPATH_D3D11:
5767         case RENDERPATH_SOFT:
5768                 break;
5769         }
5770         GL_CullFace(GL_NONE);
5771
5772         CHECKGLERROR
5773 }
5774
5775 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5776 {
5777         DrawQ_Finish();
5778
5779         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5780 }
5781
5782 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5783 {
5784         DrawQ_Finish();
5785
5786         R_SetupView(true, fbo, depthtexture, colortexture);
5787         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5788         GL_Color(1, 1, 1, 1);
5789         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5790         GL_BlendFunc(GL_ONE, GL_ZERO);
5791         GL_ScissorTest(true);
5792         GL_DepthMask(true);
5793         GL_DepthRange(0, 1);
5794         GL_DepthTest(true);
5795         GL_DepthFunc(GL_LEQUAL);
5796         R_EntityMatrix(&identitymatrix);
5797         R_Mesh_ResetTextureState();
5798         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5799         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5800         switch(vid.renderpath)
5801         {
5802         case RENDERPATH_GL11:
5803         case RENDERPATH_GL13:
5804         case RENDERPATH_GL20:
5805         case RENDERPATH_GLES1:
5806         case RENDERPATH_GLES2:
5807                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5808                 break;
5809         case RENDERPATH_D3D9:
5810         case RENDERPATH_D3D10:
5811         case RENDERPATH_D3D11:
5812         case RENDERPATH_SOFT:
5813                 break;
5814         }
5815         GL_CullFace(r_refdef.view.cullface_back);
5816 }
5817
5818 /*
5819 ================
5820 R_RenderView_UpdateViewVectors
5821 ================
5822 */
5823 void R_RenderView_UpdateViewVectors(void)
5824 {
5825         // break apart the view matrix into vectors for various purposes
5826         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5827         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5828         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5829         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5830         // make an inverted copy of the view matrix for tracking sprites
5831         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5832 }
5833
5834 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5835 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5836
5837 static void R_Water_StartFrame(void)
5838 {
5839         int i;
5840         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5841         r_waterstate_waterplane_t *p;
5842         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;
5843
5844         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5845                 return;
5846
5847         switch(vid.renderpath)
5848         {
5849         case RENDERPATH_GL20:
5850         case RENDERPATH_D3D9:
5851         case RENDERPATH_D3D10:
5852         case RENDERPATH_D3D11:
5853         case RENDERPATH_SOFT:
5854         case RENDERPATH_GLES2:
5855                 break;
5856         case RENDERPATH_GL11:
5857         case RENDERPATH_GL13:
5858         case RENDERPATH_GLES1:
5859                 return;
5860         }
5861
5862         // set waterwidth and waterheight to the water resolution that will be
5863         // used (often less than the screen resolution for faster rendering)
5864         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5865
5866         // calculate desired texture sizes
5867         // can't use water if the card does not support the texture size
5868         if (!r_water.integer || r_showsurfaces.integer)
5869                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5870         else if (vid.support.arb_texture_non_power_of_two)
5871         {
5872                 texturewidth = waterwidth;
5873                 textureheight = waterheight;
5874                 camerawidth = waterwidth;
5875                 cameraheight = waterheight;
5876         }
5877         else
5878         {
5879                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5880                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5881                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5882                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5883         }
5884
5885         // allocate textures as needed
5886         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))
5887         {
5888                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5889                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5890                 {
5891                         if (p->texture_refraction)
5892                                 R_FreeTexture(p->texture_refraction);
5893                         p->texture_refraction = NULL;
5894                         if (p->fbo_refraction)
5895                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5896                         p->fbo_refraction = 0;
5897                         if (p->texture_reflection)
5898                                 R_FreeTexture(p->texture_reflection);
5899                         p->texture_reflection = NULL;
5900                         if (p->fbo_reflection)
5901                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5902                         p->fbo_reflection = 0;
5903                         if (p->texture_camera)
5904                                 R_FreeTexture(p->texture_camera);
5905                         p->texture_camera = NULL;
5906                         if (p->fbo_camera)
5907                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5908                         p->fbo_camera = 0;
5909                 }
5910                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5911                 r_fb.water.texturewidth = texturewidth;
5912                 r_fb.water.textureheight = textureheight;
5913                 r_fb.water.camerawidth = camerawidth;
5914                 r_fb.water.cameraheight = cameraheight;
5915         }
5916
5917         if (r_fb.water.texturewidth)
5918         {
5919                 int scaledwidth, scaledheight;
5920
5921                 r_fb.water.enabled = true;
5922
5923                 // water resolution is usually reduced
5924                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5925                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5926                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5927
5928                 // set up variables that will be used in shader setup
5929                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5930                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5931                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5932                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5933         }
5934
5935         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5936         r_fb.water.numwaterplanes = 0;
5937 }
5938
5939 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5940 {
5941         int planeindex, bestplaneindex, vertexindex;
5942         vec3_t mins, maxs, normal, center, v, n;
5943         vec_t planescore, bestplanescore;
5944         mplane_t plane;
5945         r_waterstate_waterplane_t *p;
5946         texture_t *t = R_GetCurrentTexture(surface->texture);
5947
5948         rsurface.texture = t;
5949         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5950         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5951         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5952                 return;
5953         // average the vertex normals, find the surface bounds (after deformvertexes)
5954         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5955         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5956         VectorCopy(n, normal);
5957         VectorCopy(v, mins);
5958         VectorCopy(v, maxs);
5959         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5960         {
5961                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5962                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5963                 VectorAdd(normal, n, normal);
5964                 mins[0] = min(mins[0], v[0]);
5965                 mins[1] = min(mins[1], v[1]);
5966                 mins[2] = min(mins[2], v[2]);
5967                 maxs[0] = max(maxs[0], v[0]);
5968                 maxs[1] = max(maxs[1], v[1]);
5969                 maxs[2] = max(maxs[2], v[2]);
5970         }
5971         VectorNormalize(normal);
5972         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5973
5974         VectorCopy(normal, plane.normal);
5975         VectorNormalize(plane.normal);
5976         plane.dist = DotProduct(center, plane.normal);
5977         PlaneClassify(&plane);
5978         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5979         {
5980                 // skip backfaces (except if nocullface is set)
5981 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5982 //                      return;
5983                 VectorNegate(plane.normal, plane.normal);
5984                 plane.dist *= -1;
5985                 PlaneClassify(&plane);
5986         }
5987
5988
5989         // find a matching plane if there is one
5990         bestplaneindex = -1;
5991         bestplanescore = 1048576.0f;
5992         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5993         {
5994                 if(p->camera_entity == t->camera_entity)
5995                 {
5996                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5997                         if (bestplaneindex < 0 || bestplanescore > planescore)
5998                         {
5999                                 bestplaneindex = planeindex;
6000                                 bestplanescore = planescore;
6001                         }
6002                 }
6003         }
6004         planeindex = bestplaneindex;
6005         p = r_fb.water.waterplanes + planeindex;
6006
6007         // if this surface does not fit any known plane rendered this frame, add one
6008         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6009         {
6010                 // store the new plane
6011                 planeindex = r_fb.water.numwaterplanes++;
6012                 p = r_fb.water.waterplanes + planeindex;
6013                 p->plane = plane;
6014                 // clear materialflags and pvs
6015                 p->materialflags = 0;
6016                 p->pvsvalid = false;
6017                 p->camera_entity = t->camera_entity;
6018                 VectorCopy(mins, p->mins);
6019                 VectorCopy(maxs, p->maxs);
6020         }
6021         else
6022         {
6023                 // merge mins/maxs when we're adding this surface to the plane
6024                 p->mins[0] = min(p->mins[0], mins[0]);
6025                 p->mins[1] = min(p->mins[1], mins[1]);
6026                 p->mins[2] = min(p->mins[2], mins[2]);
6027                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6028                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6029                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6030         }
6031         // merge this surface's materialflags into the waterplane
6032         p->materialflags |= t->currentmaterialflags;
6033         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6034         {
6035                 // merge this surface's PVS into the waterplane
6036                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6037                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6038                 {
6039                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6040                         p->pvsvalid = true;
6041                 }
6042         }
6043 }
6044
6045 extern cvar_t r_drawparticles;
6046 extern cvar_t r_drawdecals;
6047
6048 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6049 {
6050         int myscissor[4];
6051         r_refdef_view_t originalview;
6052         r_refdef_view_t myview;
6053         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;
6054         r_waterstate_waterplane_t *p;
6055         vec3_t visorigin;
6056         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;
6057         char vabuf[1024];
6058
6059         originalview = r_refdef.view;
6060
6061         // lowquality hack, temporarily shut down some cvars and restore afterwards
6062         qualityreduction = r_water_lowquality.integer;
6063         if (qualityreduction > 0)
6064         {
6065                 if (qualityreduction >= 1)
6066                 {
6067                         old_r_shadows = r_shadows.integer;
6068                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6069                         old_r_dlight = r_shadow_realtime_dlight.integer;
6070                         Cvar_SetValueQuick(&r_shadows, 0);
6071                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6072                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6073                 }
6074                 if (qualityreduction >= 2)
6075                 {
6076                         old_r_dynamic = r_dynamic.integer;
6077                         old_r_particles = r_drawparticles.integer;
6078                         old_r_decals = r_drawdecals.integer;
6079                         Cvar_SetValueQuick(&r_dynamic, 0);
6080                         Cvar_SetValueQuick(&r_drawparticles, 0);
6081                         Cvar_SetValueQuick(&r_drawdecals, 0);
6082                 }
6083         }
6084
6085         // make sure enough textures are allocated
6086         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6087         {
6088                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6089                 {
6090                         if (!p->texture_refraction)
6091                                 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);
6092                         if (!p->texture_refraction)
6093                                 goto error;
6094                         if (usewaterfbo)
6095                         {
6096                                 if (r_fb.water.depthtexture == NULL)
6097                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6098                                 if (p->fbo_refraction == 0)
6099                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6100                         }
6101                 }
6102                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6103                 {
6104                         if (!p->texture_camera)
6105                                 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);
6106                         if (!p->texture_camera)
6107                                 goto error;
6108                         if (usewaterfbo)
6109                         {
6110                                 if (r_fb.water.depthtexture == NULL)
6111                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6112                                 if (p->fbo_camera == 0)
6113                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6114                         }
6115                 }
6116
6117                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6118                 {
6119                         if (!p->texture_reflection)
6120                                 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);
6121                         if (!p->texture_reflection)
6122                                 goto error;
6123                         if (usewaterfbo)
6124                         {
6125                                 if (r_fb.water.depthtexture == NULL)
6126                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6127                                 if (p->fbo_reflection == 0)
6128                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6129                         }
6130                 }
6131         }
6132
6133         // render views
6134         r_refdef.view = originalview;
6135         r_refdef.view.showdebug = false;
6136         r_refdef.view.width = r_fb.water.waterwidth;
6137         r_refdef.view.height = r_fb.water.waterheight;
6138         r_refdef.view.useclipplane = true;
6139         myview = r_refdef.view;
6140         r_fb.water.renderingscene = true;
6141         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6142         {
6143                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6144                 {
6145                         r_refdef.view = myview;
6146                         if(r_water_scissormode.integer)
6147                         {
6148                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6149                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6150                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6151                         }
6152
6153                         // render reflected scene and copy into texture
6154                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6155                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6156                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6157                         r_refdef.view.clipplane = p->plane;
6158                         // reverse the cullface settings for this render
6159                         r_refdef.view.cullface_front = GL_FRONT;
6160                         r_refdef.view.cullface_back = GL_BACK;
6161                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6162                         {
6163                                 r_refdef.view.usecustompvs = true;
6164                                 if (p->pvsvalid)
6165                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6166                                 else
6167                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6168                         }
6169
6170                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6171                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6172                         R_ClearScreen(r_refdef.fogenabled);
6173                         if(r_water_scissormode.integer & 2)
6174                                 R_View_UpdateWithScissor(myscissor);
6175                         else
6176                                 R_View_Update();
6177                         R_AnimCache_CacheVisibleEntities();
6178                         if(r_water_scissormode.integer & 1)
6179                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6180                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6181
6182                         if (!p->fbo_reflection)
6183                                 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);
6184                         r_fb.water.hideplayer = false;
6185                 }
6186
6187                 // render the normal view scene and copy into texture
6188                 // (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)
6189                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6190                 {
6191                         r_refdef.view = myview;
6192                         if(r_water_scissormode.integer)
6193                         {
6194                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6195                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6196                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6197                         }
6198
6199                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6200
6201                         r_refdef.view.clipplane = p->plane;
6202                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6203                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6204
6205                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6206                         {
6207                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6208                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6209                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6210                                 R_RenderView_UpdateViewVectors();
6211                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6212                                 {
6213                                         r_refdef.view.usecustompvs = true;
6214                                         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);
6215                                 }
6216                         }
6217
6218                         PlaneClassify(&r_refdef.view.clipplane);
6219
6220                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6221                         R_ClearScreen(r_refdef.fogenabled);
6222                         if(r_water_scissormode.integer & 2)
6223                                 R_View_UpdateWithScissor(myscissor);
6224                         else
6225                                 R_View_Update();
6226                         R_AnimCache_CacheVisibleEntities();
6227                         if(r_water_scissormode.integer & 1)
6228                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6229                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6230
6231                         if (!p->fbo_refraction)
6232                                 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);
6233                         r_fb.water.hideplayer = false;
6234                 }
6235                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6236                 {
6237                         r_refdef.view = myview;
6238
6239                         r_refdef.view.clipplane = p->plane;
6240                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6241                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6242
6243                         r_refdef.view.width = r_fb.water.camerawidth;
6244                         r_refdef.view.height = r_fb.water.cameraheight;
6245                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6246                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6247                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6248                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6249
6250                         if(p->camera_entity)
6251                         {
6252                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6253                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6254                         }
6255
6256                         // note: all of the view is used for displaying... so
6257                         // there is no use in scissoring
6258
6259                         // reverse the cullface settings for this render
6260                         r_refdef.view.cullface_front = GL_FRONT;
6261                         r_refdef.view.cullface_back = GL_BACK;
6262                         // also reverse the view matrix
6263                         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
6264                         R_RenderView_UpdateViewVectors();
6265                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6266                         {
6267                                 r_refdef.view.usecustompvs = true;
6268                                 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);
6269                         }
6270                         
6271                         // camera needs no clipplane
6272                         r_refdef.view.useclipplane = false;
6273
6274                         PlaneClassify(&r_refdef.view.clipplane);
6275
6276                         r_fb.water.hideplayer = false;
6277
6278                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6279                         R_ClearScreen(r_refdef.fogenabled);
6280                         R_View_Update();
6281                         R_AnimCache_CacheVisibleEntities();
6282                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6283
6284                         if (!p->fbo_camera)
6285                                 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);
6286                         r_fb.water.hideplayer = false;
6287                 }
6288
6289         }
6290         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6291         r_fb.water.renderingscene = false;
6292         r_refdef.view = originalview;
6293         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6294         if (!r_fb.water.depthtexture)
6295                 R_ClearScreen(r_refdef.fogenabled);
6296         R_View_Update();
6297         R_AnimCache_CacheVisibleEntities();
6298         goto finish;
6299 error:
6300         r_refdef.view = originalview;
6301         r_fb.water.renderingscene = false;
6302         Cvar_SetValueQuick(&r_water, 0);
6303         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6304 finish:
6305         // lowquality hack, restore cvars
6306         if (qualityreduction > 0)
6307         {
6308                 if (qualityreduction >= 1)
6309                 {
6310                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6311                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6312                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6313                 }
6314                 if (qualityreduction >= 2)
6315                 {
6316                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6317                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6318                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6319                 }
6320         }
6321 }
6322
6323 static void R_Bloom_StartFrame(void)
6324 {
6325         int i;
6326         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6327         int viewwidth, viewheight;
6328         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6329         textype_t textype = TEXTYPE_COLORBUFFER;
6330
6331         switch (vid.renderpath)
6332         {
6333         case RENDERPATH_GL20:
6334                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6335                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6336                 {
6337                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6338                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6339                 }
6340                 break;
6341         case RENDERPATH_GL11:
6342         case RENDERPATH_GL13:
6343         case RENDERPATH_GLES1:
6344         case RENDERPATH_GLES2:
6345         case RENDERPATH_D3D9:
6346         case RENDERPATH_D3D10:
6347         case RENDERPATH_D3D11:
6348                 r_fb.usedepthtextures = false;
6349                 break;
6350         case RENDERPATH_SOFT:
6351                 r_fb.usedepthtextures = true;
6352                 break;
6353         }
6354
6355         if (r_viewscale_fpsscaling.integer)
6356         {
6357                 double actualframetime;
6358                 double targetframetime;
6359                 double adjust;
6360                 actualframetime = r_refdef.lastdrawscreentime;
6361                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6362                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6363                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6364                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6365                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6366                 viewscalefpsadjusted += adjust;
6367                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6368         }
6369         else
6370                 viewscalefpsadjusted = 1.0f;
6371
6372         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6373
6374         switch(vid.renderpath)
6375         {
6376         case RENDERPATH_GL20:
6377         case RENDERPATH_D3D9:
6378         case RENDERPATH_D3D10:
6379         case RENDERPATH_D3D11:
6380         case RENDERPATH_SOFT:
6381         case RENDERPATH_GLES2:
6382                 break;
6383         case RENDERPATH_GL11:
6384         case RENDERPATH_GL13:
6385         case RENDERPATH_GLES1:
6386                 return;
6387         }
6388
6389         // set bloomwidth and bloomheight to the bloom resolution that will be
6390         // used (often less than the screen resolution for faster rendering)
6391         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6392         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6393         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6394         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6395         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6396
6397         // calculate desired texture sizes
6398         if (vid.support.arb_texture_non_power_of_two)
6399         {
6400                 screentexturewidth = vid.width;
6401                 screentextureheight = vid.height;
6402                 bloomtexturewidth = r_fb.bloomwidth;
6403                 bloomtextureheight = r_fb.bloomheight;
6404         }
6405         else
6406         {
6407                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6408                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6409                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6410                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6411         }
6412
6413         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))
6414         {
6415                 Cvar_SetValueQuick(&r_bloom, 0);
6416                 Cvar_SetValueQuick(&r_motionblur, 0);
6417                 Cvar_SetValueQuick(&r_damageblur, 0);
6418         }
6419
6420         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6421          && !r_bloom.integer
6422          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6423          && !useviewfbo
6424          && r_viewscale.value == 1.0f
6425          && !r_viewscale_fpsscaling.integer)
6426                 screentexturewidth = screentextureheight = 0;
6427         if (!r_bloom.integer)
6428                 bloomtexturewidth = bloomtextureheight = 0;
6429
6430         // allocate textures as needed
6431         if (r_fb.screentexturewidth != screentexturewidth
6432          || r_fb.screentextureheight != screentextureheight
6433          || r_fb.bloomtexturewidth != bloomtexturewidth
6434          || r_fb.bloomtextureheight != bloomtextureheight
6435          || r_fb.textype != textype
6436          || useviewfbo != (r_fb.fbo != 0))
6437         {
6438                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6439                 {
6440                         if (r_fb.bloomtexture[i])
6441                                 R_FreeTexture(r_fb.bloomtexture[i]);
6442                         r_fb.bloomtexture[i] = NULL;
6443
6444                         if (r_fb.bloomfbo[i])
6445                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6446                         r_fb.bloomfbo[i] = 0;
6447                 }
6448
6449                 if (r_fb.fbo)
6450                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6451                 r_fb.fbo = 0;
6452
6453                 if (r_fb.colortexture)
6454                         R_FreeTexture(r_fb.colortexture);
6455                 r_fb.colortexture = NULL;
6456
6457                 if (r_fb.depthtexture)
6458                         R_FreeTexture(r_fb.depthtexture);
6459                 r_fb.depthtexture = NULL;
6460
6461                 if (r_fb.ghosttexture)
6462                         R_FreeTexture(r_fb.ghosttexture);
6463                 r_fb.ghosttexture = NULL;
6464
6465                 r_fb.screentexturewidth = screentexturewidth;
6466                 r_fb.screentextureheight = screentextureheight;
6467                 r_fb.bloomtexturewidth = bloomtexturewidth;
6468                 r_fb.bloomtextureheight = bloomtextureheight;
6469                 r_fb.textype = textype;
6470
6471                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6472                 {
6473                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6474                                 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);
6475                         r_fb.ghosttexture_valid = false;
6476                         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);
6477                         if (useviewfbo)
6478                         {
6479                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6480                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6481                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6482                         }
6483                 }
6484
6485                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6486                 {
6487                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6488                         {
6489                                 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);
6490                                 if (useviewfbo)
6491                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6492                         }
6493                 }
6494         }
6495
6496         // bloom texture is a different resolution
6497         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6498         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6499         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6500         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6501         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6502
6503         // set up a texcoord array for the full resolution screen image
6504         // (we have to keep this around to copy back during final render)
6505         r_fb.screentexcoord2f[0] = 0;
6506         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6507         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6508         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6509         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6510         r_fb.screentexcoord2f[5] = 0;
6511         r_fb.screentexcoord2f[6] = 0;
6512         r_fb.screentexcoord2f[7] = 0;
6513
6514         if(r_fb.fbo) 
6515         {
6516                 for (i = 1;i < 8;i += 2)
6517                 {
6518                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6519                 }
6520         }
6521
6522         // set up a texcoord array for the reduced resolution bloom image
6523         // (which will be additive blended over the screen image)
6524         r_fb.bloomtexcoord2f[0] = 0;
6525         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6526         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6527         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6528         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6529         r_fb.bloomtexcoord2f[5] = 0;
6530         r_fb.bloomtexcoord2f[6] = 0;
6531         r_fb.bloomtexcoord2f[7] = 0;
6532
6533         switch(vid.renderpath)
6534         {
6535         case RENDERPATH_GL11:
6536         case RENDERPATH_GL13:
6537         case RENDERPATH_GL20:
6538         case RENDERPATH_SOFT:
6539         case RENDERPATH_GLES1:
6540         case RENDERPATH_GLES2:
6541                 break;
6542         case RENDERPATH_D3D9:
6543         case RENDERPATH_D3D10:
6544         case RENDERPATH_D3D11:
6545                 for (i = 0;i < 4;i++)
6546                 {
6547                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6548                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6549                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6550                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6551                 }
6552                 break;
6553         }
6554
6555         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6556
6557         if (r_fb.fbo)
6558                 r_refdef.view.clear = true;
6559 }
6560
6561 static void R_Bloom_MakeTexture(void)
6562 {
6563         int x, range, dir;
6564         float xoffset, yoffset, r, brighten;
6565         rtexture_t *intex;
6566         float colorscale = r_bloom_colorscale.value;
6567
6568         r_refdef.stats[r_stat_bloom]++;
6569     
6570 #if 0
6571     // this copy is unnecessary since it happens in R_BlendView already
6572         if (!r_fb.fbo)
6573         {
6574                 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);
6575                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6576         }
6577 #endif
6578
6579         // scale down screen texture to the bloom texture size
6580         CHECKGLERROR
6581         r_fb.bloomindex = 0;
6582         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6583         R_SetViewport(&r_fb.bloomviewport);
6584         GL_DepthTest(false);
6585         GL_BlendFunc(GL_ONE, GL_ZERO);
6586         GL_Color(colorscale, colorscale, colorscale, 1);
6587         // 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...
6588         switch(vid.renderpath)
6589         {
6590         case RENDERPATH_GL11:
6591         case RENDERPATH_GL13:
6592         case RENDERPATH_GL20:
6593         case RENDERPATH_GLES1:
6594         case RENDERPATH_GLES2:
6595         case RENDERPATH_SOFT:
6596                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6597                 break;
6598         case RENDERPATH_D3D9:
6599         case RENDERPATH_D3D10:
6600         case RENDERPATH_D3D11:
6601                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6602                 break;
6603         }
6604         // TODO: do boxfilter scale-down in shader?
6605         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6606         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6607         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6608
6609         // we now have a properly scaled bloom image
6610         if (!r_fb.bloomfbo[r_fb.bloomindex])
6611         {
6612                 // copy it into the bloom texture
6613                 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);
6614                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6615         }
6616
6617         // multiply bloom image by itself as many times as desired
6618         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6619         {
6620                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6621                 r_fb.bloomindex ^= 1;
6622                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6623                 x *= 2;
6624                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6625                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6626                 {
6627                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6628                         GL_Color(r,r,r,1); // apply fix factor
6629                 }
6630                 else
6631                 {
6632                         if(x <= 2)
6633                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6634                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6635                         GL_Color(1,1,1,1); // no fix factor supported here
6636                 }
6637                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6638                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6639                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6640                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6641
6642                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6643                 {
6644                         // copy the darkened image to a texture
6645                         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);
6646                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6647                 }
6648         }
6649
6650         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6651         brighten = r_bloom_brighten.value;
6652         brighten = sqrt(brighten);
6653         if(range >= 1)
6654                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6655
6656         for (dir = 0;dir < 2;dir++)
6657         {
6658                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6659                 r_fb.bloomindex ^= 1;
6660                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6661                 // blend on at multiple vertical offsets to achieve a vertical blur
6662                 // TODO: do offset blends using GLSL
6663                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6664                 GL_BlendFunc(GL_ONE, GL_ZERO);
6665                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6666                 for (x = -range;x <= range;x++)
6667                 {
6668                         if (!dir){xoffset = 0;yoffset = x;}
6669                         else {xoffset = x;yoffset = 0;}
6670                         xoffset /= (float)r_fb.bloomtexturewidth;
6671                         yoffset /= (float)r_fb.bloomtextureheight;
6672                         // compute a texcoord array with the specified x and y offset
6673                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6674                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6675                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6676                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6677                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6678                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6679                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6680                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6681                         // this r value looks like a 'dot' particle, fading sharply to
6682                         // black at the edges
6683                         // (probably not realistic but looks good enough)
6684                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6685                         //r = brighten/(range*2+1);
6686                         r = brighten / (range * 2 + 1);
6687                         if(range >= 1)
6688                                 r *= (1 - x*x/(float)(range*range));
6689                         GL_Color(r, r, r, 1);
6690                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6691                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6692                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6693                         GL_BlendFunc(GL_ONE, GL_ONE);
6694                 }
6695
6696                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6697                 {
6698                         // copy the vertically or horizontally blurred bloom view to a texture
6699                         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);
6700                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6701                 }
6702         }
6703 }
6704
6705 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6706 {
6707         unsigned int permutation;
6708         float uservecs[4][4];
6709
6710         R_EntityMatrix(&identitymatrix);
6711
6712         switch (vid.renderpath)
6713         {
6714         case RENDERPATH_GL20:
6715         case RENDERPATH_D3D9:
6716         case RENDERPATH_D3D10:
6717         case RENDERPATH_D3D11:
6718         case RENDERPATH_SOFT:
6719         case RENDERPATH_GLES2:
6720                 permutation =
6721                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6722                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6723                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6724                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6725                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6726
6727                 if (r_fb.colortexture)
6728                 {
6729                         if (!r_fb.fbo)
6730                         {
6731                                 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);
6732                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6733                         }
6734
6735                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6736                         {
6737                                 // declare variables
6738                                 float blur_factor, blur_mouseaccel, blur_velocity;
6739                                 static float blur_average; 
6740                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6741
6742                                 // set a goal for the factoring
6743                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6744                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6745                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6746                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6747                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6748                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6749
6750                                 // from the goal, pick an averaged value between goal and last value
6751                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6752                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6753
6754                                 // enforce minimum amount of blur 
6755                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6756
6757                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6758
6759                                 // calculate values into a standard alpha
6760                                 cl.motionbluralpha = 1 - exp(-
6761                                                 (
6762                                                  (r_motionblur.value * blur_factor / 80)
6763                                                  +
6764                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6765                                                 )
6766                                                 /
6767                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6768                                           );
6769
6770                                 // randomization for the blur value to combat persistent ghosting
6771                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6772                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6773
6774                                 // apply the blur
6775                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6776                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6777                                 {
6778                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6779                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6780                                         switch(vid.renderpath)
6781                                         {
6782                                         case RENDERPATH_GL11:
6783                                         case RENDERPATH_GL13:
6784                                         case RENDERPATH_GL20:
6785                                         case RENDERPATH_GLES1:
6786                                         case RENDERPATH_GLES2:
6787                                         case RENDERPATH_SOFT:
6788                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6789                                                 break;
6790                                         case RENDERPATH_D3D9:
6791                                         case RENDERPATH_D3D10:
6792                                         case RENDERPATH_D3D11:
6793                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6794                                                 break;
6795                                         }
6796                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6797                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6798                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6799                                 }
6800
6801                                 // updates old view angles for next pass
6802                                 VectorCopy(cl.viewangles, blur_oldangles);
6803
6804                                 // copy view into the ghost texture
6805                                 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);
6806                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6807                                 r_fb.ghosttexture_valid = true;
6808                         }
6809                 }
6810                 else
6811                 {
6812                         // no r_fb.colortexture means we're rendering to the real fb
6813                         // we may still have to do view tint...
6814                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6815                         {
6816                                 // apply a color tint to the whole view
6817                                 R_ResetViewRendering2D(0, NULL, NULL);
6818                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6819                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6820                                 R_SetupShader_Generic_NoTexture(false, true);
6821                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6822                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6823                         }
6824                         break; // no screen processing, no bloom, skip it
6825                 }
6826
6827                 if (r_fb.bloomtexture[0])
6828                 {
6829                         // make the bloom texture
6830                         R_Bloom_MakeTexture();
6831                 }
6832
6833 #if _MSC_VER >= 1400
6834 #define sscanf sscanf_s
6835 #endif
6836                 memset(uservecs, 0, sizeof(uservecs));
6837                 if (r_glsl_postprocess_uservec1_enable.integer)
6838                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6839                 if (r_glsl_postprocess_uservec2_enable.integer)
6840                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6841                 if (r_glsl_postprocess_uservec3_enable.integer)
6842                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6843                 if (r_glsl_postprocess_uservec4_enable.integer)
6844                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6845
6846                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6847                 GL_Color(1, 1, 1, 1);
6848                 GL_BlendFunc(GL_ONE, GL_ZERO);
6849
6850                 switch(vid.renderpath)
6851                 {
6852                 case RENDERPATH_GL20:
6853                 case RENDERPATH_GLES2:
6854                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6855                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6856                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6857                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6858                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6859                         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]);
6860                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6861                         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]);
6862                         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]);
6863                         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]);
6864                         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]);
6865                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6866                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6867                         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);
6868                         break;
6869                 case RENDERPATH_D3D9:
6870 #ifdef SUPPORTD3D
6871                         // 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...
6872                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6873                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6874                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6875                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6876                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6877                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6878                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6879                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6880                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6881                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6882                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6883                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6884                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6885                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6886 #endif
6887                         break;
6888                 case RENDERPATH_D3D10:
6889                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6890                         break;
6891                 case RENDERPATH_D3D11:
6892                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6893                         break;
6894                 case RENDERPATH_SOFT:
6895                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6896                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6897                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6898                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6899                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6900                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6901                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6902                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6903                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6904                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6905                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6906                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6907                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6908                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6909                         break;
6910                 default:
6911                         break;
6912                 }
6913                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6914                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6915                 break;
6916         case RENDERPATH_GL11:
6917         case RENDERPATH_GL13:
6918         case RENDERPATH_GLES1:
6919                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6920                 {
6921                         // apply a color tint to the whole view
6922                         R_ResetViewRendering2D(0, NULL, NULL);
6923                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6924                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6925                         R_SetupShader_Generic_NoTexture(false, true);
6926                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6927                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6928                 }
6929                 break;
6930         }
6931 }
6932
6933 matrix4x4_t r_waterscrollmatrix;
6934
6935 void R_UpdateFog(void)
6936 {
6937         // Nehahra fog
6938         if (gamemode == GAME_NEHAHRA)
6939         {
6940                 if (gl_fogenable.integer)
6941                 {
6942                         r_refdef.oldgl_fogenable = true;
6943                         r_refdef.fog_density = gl_fogdensity.value;
6944                         r_refdef.fog_red = gl_fogred.value;
6945                         r_refdef.fog_green = gl_foggreen.value;
6946                         r_refdef.fog_blue = gl_fogblue.value;
6947                         r_refdef.fog_alpha = 1;
6948                         r_refdef.fog_start = 0;
6949                         r_refdef.fog_end = gl_skyclip.value;
6950                         r_refdef.fog_height = 1<<30;
6951                         r_refdef.fog_fadedepth = 128;
6952                 }
6953                 else if (r_refdef.oldgl_fogenable)
6954                 {
6955                         r_refdef.oldgl_fogenable = false;
6956                         r_refdef.fog_density = 0;
6957                         r_refdef.fog_red = 0;
6958                         r_refdef.fog_green = 0;
6959                         r_refdef.fog_blue = 0;
6960                         r_refdef.fog_alpha = 0;
6961                         r_refdef.fog_start = 0;
6962                         r_refdef.fog_end = 0;
6963                         r_refdef.fog_height = 1<<30;
6964                         r_refdef.fog_fadedepth = 128;
6965                 }
6966         }
6967
6968         // fog parms
6969         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6970         r_refdef.fog_start = max(0, r_refdef.fog_start);
6971         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6972
6973         if (r_refdef.fog_density && r_drawfog.integer)
6974         {
6975                 r_refdef.fogenabled = true;
6976                 // this is the point where the fog reaches 0.9986 alpha, which we
6977                 // consider a good enough cutoff point for the texture
6978                 // (0.9986 * 256 == 255.6)
6979                 if (r_fog_exp2.integer)
6980                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6981                 else
6982                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6983                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6984                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6985                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6986                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6987                         R_BuildFogHeightTexture();
6988                 // fog color was already set
6989                 // update the fog texture
6990                 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)
6991                         R_BuildFogTexture();
6992                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6993                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6994         }
6995         else
6996                 r_refdef.fogenabled = false;
6997
6998         // fog color
6999         if (r_refdef.fog_density)
7000         {
7001                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7002                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7003                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7004
7005                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7006                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7007                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7008                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7009
7010                 {
7011                         vec3_t fogvec;
7012                         VectorCopy(r_refdef.fogcolor, fogvec);
7013                         //   color.rgb *= ContrastBoost * SceneBrightness;
7014                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7015                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7016                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7017                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7018                 }
7019         }
7020 }
7021
7022 void R_UpdateVariables(void)
7023 {
7024         R_Textures_Frame();
7025
7026         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7027
7028         r_refdef.farclip = r_farclip_base.value;
7029         if (r_refdef.scene.worldmodel)
7030                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7031         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7032
7033         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7034                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7035         r_refdef.polygonfactor = 0;
7036         r_refdef.polygonoffset = 0;
7037         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7038         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7039
7040         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7041         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7042         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7043         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7044         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7045         if (FAKELIGHT_ENABLED)
7046         {
7047                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7048         }
7049         else if (r_refdef.scene.worldmodel)
7050         {
7051                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7052         }
7053         if (r_showsurfaces.integer)
7054         {
7055                 r_refdef.scene.rtworld = false;
7056                 r_refdef.scene.rtworldshadows = false;
7057                 r_refdef.scene.rtdlight = false;
7058                 r_refdef.scene.rtdlightshadows = false;
7059                 r_refdef.lightmapintensity = 0;
7060         }
7061
7062         r_gpuskeletal = false;
7063         switch(vid.renderpath)
7064         {
7065         case RENDERPATH_GL20:
7066                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7067         case RENDERPATH_D3D9:
7068         case RENDERPATH_D3D10:
7069         case RENDERPATH_D3D11:
7070         case RENDERPATH_SOFT:
7071         case RENDERPATH_GLES2:
7072                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7073                 {
7074                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7075                         {
7076                                 // build GLSL gamma texture
7077 #define RAMPWIDTH 256
7078                                 unsigned short ramp[RAMPWIDTH * 3];
7079                                 unsigned char rampbgr[RAMPWIDTH][4];
7080                                 int i;
7081
7082                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7083
7084                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7085                                 for(i = 0; i < RAMPWIDTH; ++i)
7086                                 {
7087                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7088                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7089                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7090                                         rampbgr[i][3] = 0;
7091                                 }
7092                                 if (r_texture_gammaramps)
7093                                 {
7094                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7095                                 }
7096                                 else
7097                                 {
7098                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7099                                 }
7100                         }
7101                 }
7102                 else
7103                 {
7104                         // remove GLSL gamma texture
7105                 }
7106                 break;
7107         case RENDERPATH_GL11:
7108         case RENDERPATH_GL13:
7109         case RENDERPATH_GLES1:
7110                 break;
7111         }
7112 }
7113
7114 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7115 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7116 /*
7117 ================
7118 R_SelectScene
7119 ================
7120 */
7121 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7122         if( scenetype != r_currentscenetype ) {
7123                 // store the old scenetype
7124                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7125                 r_currentscenetype = scenetype;
7126                 // move in the new scene
7127                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7128         }
7129 }
7130
7131 /*
7132 ================
7133 R_GetScenePointer
7134 ================
7135 */
7136 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7137 {
7138         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7139         if( scenetype == r_currentscenetype ) {
7140                 return &r_refdef.scene;
7141         } else {
7142                 return &r_scenes_store[ scenetype ];
7143         }
7144 }
7145
7146 static int R_SortEntities_Compare(const void *ap, const void *bp)
7147 {
7148         const entity_render_t *a = *(const entity_render_t **)ap;
7149         const entity_render_t *b = *(const entity_render_t **)bp;
7150
7151         // 1. compare model
7152         if(a->model < b->model)
7153                 return -1;
7154         if(a->model > b->model)
7155                 return +1;
7156
7157         // 2. compare skin
7158         // TODO possibly calculate the REAL skinnum here first using
7159         // skinscenes?
7160         if(a->skinnum < b->skinnum)
7161                 return -1;
7162         if(a->skinnum > b->skinnum)
7163                 return +1;
7164
7165         // everything we compared is equal
7166         return 0;
7167 }
7168 static void R_SortEntities(void)
7169 {
7170         // below or equal 2 ents, sorting never gains anything
7171         if(r_refdef.scene.numentities <= 2)
7172                 return;
7173         // sort
7174         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7175 }
7176
7177 /*
7178 ================
7179 R_RenderView
7180 ================
7181 */
7182 int dpsoftrast_test;
7183 extern cvar_t r_shadow_bouncegrid;
7184 void R_RenderView(void)
7185 {
7186         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7187         int fbo;
7188         rtexture_t *depthtexture;
7189         rtexture_t *colortexture;
7190
7191         dpsoftrast_test = r_test.integer;
7192
7193         if (r_timereport_active)
7194                 R_TimeReport("start");
7195         r_textureframe++; // used only by R_GetCurrentTexture
7196         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7197
7198         if(R_CompileShader_CheckStaticParms())
7199                 R_GLSL_Restart_f();
7200
7201         if (!r_drawentities.integer)
7202                 r_refdef.scene.numentities = 0;
7203         else if (r_sortentities.integer)
7204                 R_SortEntities();
7205
7206         R_AnimCache_ClearCache();
7207         R_FrameData_NewFrame();
7208         R_BufferData_NewFrame();
7209
7210         /* adjust for stereo display */
7211         if(R_Stereo_Active())
7212         {
7213                 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);
7214                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7215         }
7216
7217         if (r_refdef.view.isoverlay)
7218         {
7219                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7220                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7221                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7222                 R_TimeReport("depthclear");
7223
7224                 r_refdef.view.showdebug = false;
7225
7226                 r_fb.water.enabled = false;
7227                 r_fb.water.numwaterplanes = 0;
7228
7229                 R_RenderScene(0, NULL, NULL);
7230
7231                 r_refdef.view.matrix = originalmatrix;
7232
7233                 CHECKGLERROR
7234                 return;
7235         }
7236
7237         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7238         {
7239                 r_refdef.view.matrix = originalmatrix;
7240                 return;
7241         }
7242
7243         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7244
7245         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7246                 // in sRGB fallback, behave similar to true sRGB: convert this
7247                 // value from linear to sRGB
7248                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7249
7250         R_RenderView_UpdateViewVectors();
7251
7252         R_Shadow_UpdateWorldLightSelection();
7253
7254         R_Bloom_StartFrame();
7255
7256         // apply bloom brightness offset
7257         if(r_fb.bloomtexture[0])
7258                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7259
7260         R_Water_StartFrame();
7261
7262         // now we probably have an fbo to render into
7263         fbo = r_fb.fbo;
7264         depthtexture = r_fb.depthtexture;
7265         colortexture = r_fb.colortexture;
7266
7267         CHECKGLERROR
7268         if (r_timereport_active)
7269                 R_TimeReport("viewsetup");
7270
7271         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7272
7273         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7274         {
7275                 R_ClearScreen(r_refdef.fogenabled);
7276                 if (r_timereport_active)
7277                         R_TimeReport("viewclear");
7278         }
7279         r_refdef.view.clear = true;
7280
7281         r_refdef.view.showdebug = true;
7282
7283         R_View_Update();
7284         if (r_timereport_active)
7285                 R_TimeReport("visibility");
7286
7287         R_AnimCache_CacheVisibleEntities();
7288         if (r_timereport_active)
7289                 R_TimeReport("animcache");
7290
7291         R_Shadow_UpdateBounceGridTexture();
7292         if (r_timereport_active && r_shadow_bouncegrid.integer)
7293                 R_TimeReport("bouncegrid");
7294
7295         r_fb.water.numwaterplanes = 0;
7296         if (r_fb.water.enabled)
7297                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7298
7299         R_RenderScene(fbo, depthtexture, colortexture);
7300         r_fb.water.numwaterplanes = 0;
7301
7302         R_BlendView(fbo, depthtexture, colortexture);
7303         if (r_timereport_active)
7304                 R_TimeReport("blendview");
7305
7306         GL_Scissor(0, 0, vid.width, vid.height);
7307         GL_ScissorTest(false);
7308
7309         r_refdef.view.matrix = originalmatrix;
7310
7311         CHECKGLERROR
7312 }
7313
7314 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7315 {
7316         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7317         {
7318                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7319                 if (r_timereport_active)
7320                         R_TimeReport("waterworld");
7321         }
7322
7323         // don't let sound skip if going slow
7324         if (r_refdef.scene.extraupdate)
7325                 S_ExtraUpdate ();
7326
7327         R_DrawModelsAddWaterPlanes();
7328         if (r_timereport_active)
7329                 R_TimeReport("watermodels");
7330
7331         if (r_fb.water.numwaterplanes)
7332         {
7333                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7334                 if (r_timereport_active)
7335                         R_TimeReport("waterscenes");
7336         }
7337 }
7338
7339 extern cvar_t cl_locs_show;
7340 static void R_DrawLocs(void);
7341 static void R_DrawEntityBBoxes(void);
7342 static void R_DrawModelDecals(void);
7343 extern cvar_t cl_decals_newsystem;
7344 extern qboolean r_shadow_usingdeferredprepass;
7345 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7346 {
7347         qboolean shadowmapping = false;
7348
7349         if (r_timereport_active)
7350                 R_TimeReport("beginscene");
7351
7352         r_refdef.stats[r_stat_renders]++;
7353
7354         R_UpdateFog();
7355
7356         // don't let sound skip if going slow
7357         if (r_refdef.scene.extraupdate)
7358                 S_ExtraUpdate ();
7359
7360         R_MeshQueue_BeginScene();
7361
7362         R_SkyStartFrame();
7363
7364         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);
7365
7366         if (r_timereport_active)
7367                 R_TimeReport("skystartframe");
7368
7369         if (cl.csqc_vidvars.drawworld)
7370         {
7371                 // don't let sound skip if going slow
7372                 if (r_refdef.scene.extraupdate)
7373                         S_ExtraUpdate ();
7374
7375                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7376                 {
7377                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7378                         if (r_timereport_active)
7379                                 R_TimeReport("worldsky");
7380                 }
7381
7382                 if (R_DrawBrushModelsSky() && r_timereport_active)
7383                         R_TimeReport("bmodelsky");
7384
7385                 if (skyrendermasked && skyrenderlater)
7386                 {
7387                         // we have to force off the water clipping plane while rendering sky
7388                         R_SetupView(false, fbo, depthtexture, colortexture);
7389                         R_Sky();
7390                         R_SetupView(true, fbo, depthtexture, colortexture);
7391                         if (r_timereport_active)
7392                                 R_TimeReport("sky");
7393                 }
7394         }
7395
7396         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7397         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7398                 R_Shadow_PrepareModelShadows();
7399         if (r_timereport_active)
7400                 R_TimeReport("preparelights");
7401
7402         if (R_Shadow_ShadowMappingEnabled())
7403                 shadowmapping = true;
7404
7405         if (r_shadow_usingdeferredprepass)
7406                 R_Shadow_DrawPrepass();
7407
7408         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7409         {
7410                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7411                 if (r_timereport_active)
7412                         R_TimeReport("worlddepth");
7413         }
7414         if (r_depthfirst.integer >= 2)
7415         {
7416                 R_DrawModelsDepth();
7417                 if (r_timereport_active)
7418                         R_TimeReport("modeldepth");
7419         }
7420
7421         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7422         {
7423                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7424                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7425                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7426                 // don't let sound skip if going slow
7427                 if (r_refdef.scene.extraupdate)
7428                         S_ExtraUpdate ();
7429         }
7430
7431         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7432         {
7433                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7434                 if (r_timereport_active)
7435                         R_TimeReport("world");
7436         }
7437
7438         // don't let sound skip if going slow
7439         if (r_refdef.scene.extraupdate)
7440                 S_ExtraUpdate ();
7441
7442         R_DrawModels();
7443         if (r_timereport_active)
7444                 R_TimeReport("models");
7445
7446         // don't let sound skip if going slow
7447         if (r_refdef.scene.extraupdate)
7448                 S_ExtraUpdate ();
7449
7450         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7451         {
7452                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7453                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7454                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7455                 // don't let sound skip if going slow
7456                 if (r_refdef.scene.extraupdate)
7457                         S_ExtraUpdate ();
7458         }
7459
7460         if (!r_shadow_usingdeferredprepass)
7461         {
7462                 R_Shadow_DrawLights();
7463                 if (r_timereport_active)
7464                         R_TimeReport("rtlights");
7465         }
7466
7467         // don't let sound skip if going slow
7468         if (r_refdef.scene.extraupdate)
7469                 S_ExtraUpdate ();
7470
7471         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7472         {
7473                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7474                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7475                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7476                 // don't let sound skip if going slow
7477                 if (r_refdef.scene.extraupdate)
7478                         S_ExtraUpdate ();
7479         }
7480
7481         if (cl.csqc_vidvars.drawworld)
7482         {
7483                 if (cl_decals_newsystem.integer)
7484                 {
7485                         R_DrawModelDecals();
7486                         if (r_timereport_active)
7487                                 R_TimeReport("modeldecals");
7488                 }
7489                 else
7490                 {
7491                         R_DrawDecals();
7492                         if (r_timereport_active)
7493                                 R_TimeReport("decals");
7494                 }
7495
7496                 R_DrawParticles();
7497                 if (r_timereport_active)
7498                         R_TimeReport("particles");
7499
7500                 R_DrawExplosions();
7501                 if (r_timereport_active)
7502                         R_TimeReport("explosions");
7503
7504                 R_DrawLightningBeams();
7505                 if (r_timereport_active)
7506                         R_TimeReport("lightning");
7507         }
7508
7509         if (cl.csqc_loaded)
7510                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7511
7512         if (r_refdef.view.showdebug)
7513         {
7514                 if (cl_locs_show.integer)
7515                 {
7516                         R_DrawLocs();
7517                         if (r_timereport_active)
7518                                 R_TimeReport("showlocs");
7519                 }
7520
7521                 if (r_drawportals.integer)
7522                 {
7523                         R_DrawPortals();
7524                         if (r_timereport_active)
7525                                 R_TimeReport("portals");
7526                 }
7527
7528                 if (r_showbboxes.value > 0)
7529                 {
7530                         R_DrawEntityBBoxes();
7531                         if (r_timereport_active)
7532                                 R_TimeReport("bboxes");
7533                 }
7534         }
7535
7536         if (r_transparent.integer)
7537         {
7538                 R_MeshQueue_RenderTransparent();
7539                 if (r_timereport_active)
7540                         R_TimeReport("drawtrans");
7541         }
7542
7543         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))
7544         {
7545                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7546                 if (r_timereport_active)
7547                         R_TimeReport("worlddebug");
7548                 R_DrawModelsDebug();
7549                 if (r_timereport_active)
7550                         R_TimeReport("modeldebug");
7551         }
7552
7553         if (cl.csqc_vidvars.drawworld)
7554         {
7555                 R_Shadow_DrawCoronas();
7556                 if (r_timereport_active)
7557                         R_TimeReport("coronas");
7558         }
7559
7560 #if 0
7561         {
7562                 GL_DepthTest(false);
7563                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7564                 GL_Color(1, 1, 1, 1);
7565                 qglBegin(GL_POLYGON);
7566                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7567                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7568                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7569                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7570                 qglEnd();
7571                 qglBegin(GL_POLYGON);
7572                 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]);
7573                 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]);
7574                 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]);
7575                 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]);
7576                 qglEnd();
7577                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7578         }
7579 #endif
7580
7581         // don't let sound skip if going slow
7582         if (r_refdef.scene.extraupdate)
7583                 S_ExtraUpdate ();
7584 }
7585
7586 static const unsigned short bboxelements[36] =
7587 {
7588         5, 1, 3, 5, 3, 7,
7589         6, 2, 0, 6, 0, 4,
7590         7, 3, 2, 7, 2, 6,
7591         4, 0, 1, 4, 1, 5,
7592         4, 5, 7, 4, 7, 6,
7593         1, 0, 2, 1, 2, 3,
7594 };
7595
7596 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7597 {
7598         int i;
7599         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7600
7601         RSurf_ActiveWorldEntity();
7602
7603         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7604         GL_DepthMask(false);
7605         GL_DepthRange(0, 1);
7606         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7607 //      R_Mesh_ResetTextureState();
7608
7609         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7610         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7611         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7612         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7613         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7614         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7615         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7616         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7617         R_FillColors(color4f, 8, cr, cg, cb, ca);
7618         if (r_refdef.fogenabled)
7619         {
7620                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7621                 {
7622                         f1 = RSurf_FogVertex(v);
7623                         f2 = 1 - f1;
7624                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7625                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7626                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7627                 }
7628         }
7629         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7630         R_Mesh_ResetTextureState();
7631         R_SetupShader_Generic_NoTexture(false, false);
7632         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7633 }
7634
7635 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7636 {
7637         prvm_prog_t *prog = SVVM_prog;
7638         int i;
7639         float color[4];
7640         prvm_edict_t *edict;
7641
7642         // this function draws bounding boxes of server entities
7643         if (!sv.active)
7644                 return;
7645
7646         GL_CullFace(GL_NONE);
7647         R_SetupShader_Generic_NoTexture(false, false);
7648
7649         for (i = 0;i < numsurfaces;i++)
7650         {
7651                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7652                 switch ((int)PRVM_serveredictfloat(edict, solid))
7653                 {
7654                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7655                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7656                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7657                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7658                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7659                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7660                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7661                 }
7662                 color[3] *= r_showbboxes.value;
7663                 color[3] = bound(0, color[3], 1);
7664                 GL_DepthTest(!r_showdisabledepthtest.integer);
7665                 GL_CullFace(r_refdef.view.cullface_front);
7666                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7667         }
7668 }
7669
7670 static void R_DrawEntityBBoxes(void)
7671 {
7672         int i;
7673         prvm_edict_t *edict;
7674         vec3_t center;
7675         prvm_prog_t *prog = SVVM_prog;
7676
7677         // this function draws bounding boxes of server entities
7678         if (!sv.active)
7679                 return;
7680
7681         for (i = 0;i < prog->num_edicts;i++)
7682         {
7683                 edict = PRVM_EDICT_NUM(i);
7684                 if (edict->priv.server->free)
7685                         continue;
7686                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7687                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7688                         continue;
7689                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7690                         continue;
7691                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7692                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7693         }
7694 }
7695
7696 static const int nomodelelement3i[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 unsigned short nomodelelement3s[24] =
7709 {
7710         5, 2, 0,
7711         5, 1, 2,
7712         5, 0, 3,
7713         5, 3, 1,
7714         0, 2, 4,
7715         2, 1, 4,
7716         3, 0, 4,
7717         1, 3, 4
7718 };
7719
7720 static const float nomodelvertex3f[6*3] =
7721 {
7722         -16,   0,   0,
7723          16,   0,   0,
7724           0, -16,   0,
7725           0,  16,   0,
7726           0,   0, -16,
7727           0,   0,  16
7728 };
7729
7730 static const float nomodelcolor4f[6*4] =
7731 {
7732         0.0f, 0.0f, 0.5f, 1.0f,
7733         0.0f, 0.0f, 0.5f, 1.0f,
7734         0.0f, 0.5f, 0.0f, 1.0f,
7735         0.0f, 0.5f, 0.0f, 1.0f,
7736         0.5f, 0.0f, 0.0f, 1.0f,
7737         0.5f, 0.0f, 0.0f, 1.0f
7738 };
7739
7740 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7741 {
7742         int i;
7743         float f1, f2, *c;
7744         float color4f[6*4];
7745
7746         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);
7747
7748         // this is only called once per entity so numsurfaces is always 1, and
7749         // surfacelist is always {0}, so this code does not handle batches
7750
7751         if (rsurface.ent_flags & RENDER_ADDITIVE)
7752         {
7753                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7754                 GL_DepthMask(false);
7755         }
7756         else if (rsurface.colormod[3] < 1)
7757         {
7758                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7759                 GL_DepthMask(false);
7760         }
7761         else
7762         {
7763                 GL_BlendFunc(GL_ONE, GL_ZERO);
7764                 GL_DepthMask(true);
7765         }
7766         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7767         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7768         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7769         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7770         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7771         for (i = 0, c = color4f;i < 6;i++, c += 4)
7772         {
7773                 c[0] *= rsurface.colormod[0];
7774                 c[1] *= rsurface.colormod[1];
7775                 c[2] *= rsurface.colormod[2];
7776                 c[3] *= rsurface.colormod[3];
7777         }
7778         if (r_refdef.fogenabled)
7779         {
7780                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7781                 {
7782                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7783                         f2 = 1 - f1;
7784                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7785                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7786                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7787                 }
7788         }
7789 //      R_Mesh_ResetTextureState();
7790         R_SetupShader_Generic_NoTexture(false, false);
7791         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7792         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7793 }
7794
7795 void R_DrawNoModel(entity_render_t *ent)
7796 {
7797         vec3_t org;
7798         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7799         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7800                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7801         else
7802                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7803 }
7804
7805 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7806 {
7807         vec3_t right1, right2, diff, normal;
7808
7809         VectorSubtract (org2, org1, normal);
7810
7811         // calculate 'right' vector for start
7812         VectorSubtract (r_refdef.view.origin, org1, diff);
7813         CrossProduct (normal, diff, right1);
7814         VectorNormalize (right1);
7815
7816         // calculate 'right' vector for end
7817         VectorSubtract (r_refdef.view.origin, org2, diff);
7818         CrossProduct (normal, diff, right2);
7819         VectorNormalize (right2);
7820
7821         vert[ 0] = org1[0] + width * right1[0];
7822         vert[ 1] = org1[1] + width * right1[1];
7823         vert[ 2] = org1[2] + width * right1[2];
7824         vert[ 3] = org1[0] - width * right1[0];
7825         vert[ 4] = org1[1] - width * right1[1];
7826         vert[ 5] = org1[2] - width * right1[2];
7827         vert[ 6] = org2[0] - width * right2[0];
7828         vert[ 7] = org2[1] - width * right2[1];
7829         vert[ 8] = org2[2] - width * right2[2];
7830         vert[ 9] = org2[0] + width * right2[0];
7831         vert[10] = org2[1] + width * right2[1];
7832         vert[11] = org2[2] + width * right2[2];
7833 }
7834
7835 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)
7836 {
7837         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7838         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7839         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7840         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7841         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7842         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7843         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7844         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7845         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7846         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7847         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7848         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7849 }
7850
7851 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7852 {
7853         int i;
7854         float *vertex3f;
7855         float v[3];
7856         VectorSet(v, x, y, z);
7857         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7858                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7859                         break;
7860         if (i == mesh->numvertices)
7861         {
7862                 if (mesh->numvertices < mesh->maxvertices)
7863                 {
7864                         VectorCopy(v, vertex3f);
7865                         mesh->numvertices++;
7866                 }
7867                 return mesh->numvertices;
7868         }
7869         else
7870                 return i;
7871 }
7872
7873 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7874 {
7875         int i;
7876         int *e, element[3];
7877         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7878         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7879         e = mesh->element3i + mesh->numtriangles * 3;
7880         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7881         {
7882                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7883                 if (mesh->numtriangles < mesh->maxtriangles)
7884                 {
7885                         *e++ = element[0];
7886                         *e++ = element[1];
7887                         *e++ = element[2];
7888                         mesh->numtriangles++;
7889                 }
7890                 element[1] = element[2];
7891         }
7892 }
7893
7894 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7895 {
7896         int i;
7897         int *e, element[3];
7898         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7899         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7900         e = mesh->element3i + mesh->numtriangles * 3;
7901         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7902         {
7903                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7904                 if (mesh->numtriangles < mesh->maxtriangles)
7905                 {
7906                         *e++ = element[0];
7907                         *e++ = element[1];
7908                         *e++ = element[2];
7909                         mesh->numtriangles++;
7910                 }
7911                 element[1] = element[2];
7912         }
7913 }
7914
7915 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7916 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7917 {
7918         int planenum, planenum2;
7919         int w;
7920         int tempnumpoints;
7921         mplane_t *plane, *plane2;
7922         double maxdist;
7923         double temppoints[2][256*3];
7924         // figure out how large a bounding box we need to properly compute this brush
7925         maxdist = 0;
7926         for (w = 0;w < numplanes;w++)
7927                 maxdist = max(maxdist, fabs(planes[w].dist));
7928         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7929         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7930         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7931         {
7932                 w = 0;
7933                 tempnumpoints = 4;
7934                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7935                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7936                 {
7937                         if (planenum2 == planenum)
7938                                 continue;
7939                         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);
7940                         w = !w;
7941                 }
7942                 if (tempnumpoints < 3)
7943                         continue;
7944                 // generate elements forming a triangle fan for this polygon
7945                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7946         }
7947 }
7948
7949 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)
7950 {
7951         texturelayer_t *layer;
7952         layer = t->currentlayers + t->currentnumlayers++;
7953         layer->type = type;
7954         layer->depthmask = depthmask;
7955         layer->blendfunc1 = blendfunc1;
7956         layer->blendfunc2 = blendfunc2;
7957         layer->texture = texture;
7958         layer->texmatrix = *matrix;
7959         layer->color[0] = r;
7960         layer->color[1] = g;
7961         layer->color[2] = b;
7962         layer->color[3] = a;
7963 }
7964
7965 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7966 {
7967         if(parms[0] == 0 && parms[1] == 0)
7968                 return false;
7969         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7970                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7971                         return false;
7972         return true;
7973 }
7974
7975 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7976 {
7977         double index, f;
7978         index = parms[2] + rsurface.shadertime * parms[3];
7979         index -= floor(index);
7980         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7981         {
7982         default:
7983         case Q3WAVEFUNC_NONE:
7984         case Q3WAVEFUNC_NOISE:
7985         case Q3WAVEFUNC_COUNT:
7986                 f = 0;
7987                 break;
7988         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7989         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7990         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7991         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7992         case Q3WAVEFUNC_TRIANGLE:
7993                 index *= 4;
7994                 f = index - floor(index);
7995                 if (index < 1)
7996                 {
7997                         // f = f;
7998                 }
7999                 else if (index < 2)
8000                         f = 1 - f;
8001                 else if (index < 3)
8002                         f = -f;
8003                 else
8004                         f = -(1 - f);
8005                 break;
8006         }
8007         f = parms[0] + parms[1] * f;
8008         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8009                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8010         return (float) f;
8011 }
8012
8013 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8014 {
8015         int w, h, idx;
8016         double f;
8017         double offsetd[2];
8018         float tcmat[12];
8019         matrix4x4_t matrix, temp;
8020         switch(tcmod->tcmod)
8021         {
8022                 case Q3TCMOD_COUNT:
8023                 case Q3TCMOD_NONE:
8024                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8025                                 matrix = r_waterscrollmatrix;
8026                         else
8027                                 matrix = identitymatrix;
8028                         break;
8029                 case Q3TCMOD_ENTITYTRANSLATE:
8030                         // this is used in Q3 to allow the gamecode to control texcoord
8031                         // scrolling on the entity, which is not supported in darkplaces yet.
8032                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8033                         break;
8034                 case Q3TCMOD_ROTATE:
8035                         f = tcmod->parms[0] * rsurface.shadertime;
8036                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8037                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
8038                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8039                         break;
8040                 case Q3TCMOD_SCALE:
8041                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8042                         break;
8043                 case Q3TCMOD_SCROLL:
8044                         // extra care is needed because of precision breakdown with large values of time
8045                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8046                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8047                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8048                         break;
8049                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8050                         w = (int) tcmod->parms[0];
8051                         h = (int) tcmod->parms[1];
8052                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8053                         f = f - floor(f);
8054                         idx = (int) floor(f * w * h);
8055                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8056                         break;
8057                 case Q3TCMOD_STRETCH:
8058                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8059                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8060                         break;
8061                 case Q3TCMOD_TRANSFORM:
8062                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8063                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8064                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8065                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8066                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8067                         break;
8068                 case Q3TCMOD_TURBULENT:
8069                         // this is handled in the RSurf_PrepareVertices function
8070                         matrix = identitymatrix;
8071                         break;
8072         }
8073         temp = *texmatrix;
8074         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8075 }
8076
8077 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8078 {
8079         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8080         char name[MAX_QPATH];
8081         skinframe_t *skinframe;
8082         unsigned char pixels[296*194];
8083         strlcpy(cache->name, skinname, sizeof(cache->name));
8084         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8085         if (developer_loading.integer)
8086                 Con_Printf("loading %s\n", name);
8087         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8088         if (!skinframe || !skinframe->base)
8089         {
8090                 unsigned char *f;
8091                 fs_offset_t filesize;
8092                 skinframe = NULL;
8093                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8094                 if (f)
8095                 {
8096                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8097                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8098                         Mem_Free(f);
8099                 }
8100         }
8101         cache->skinframe = skinframe;
8102 }
8103
8104 texture_t *R_GetCurrentTexture(texture_t *t)
8105 {
8106         int i;
8107         const entity_render_t *ent = rsurface.entity;
8108         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8109         q3shaderinfo_layer_tcmod_t *tcmod;
8110
8111         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8112                 return t->currentframe;
8113         t->update_lastrenderframe = r_textureframe;
8114         t->update_lastrenderentity = (void *)ent;
8115
8116         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8117                 t->camera_entity = ent->entitynumber;
8118         else
8119                 t->camera_entity = 0;
8120
8121         // switch to an alternate material if this is a q1bsp animated material
8122         {
8123                 texture_t *texture = t;
8124                 int s = rsurface.ent_skinnum;
8125                 if ((unsigned int)s >= (unsigned int)model->numskins)
8126                         s = 0;
8127                 if (model->skinscenes)
8128                 {
8129                         if (model->skinscenes[s].framecount > 1)
8130                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8131                         else
8132                                 s = model->skinscenes[s].firstframe;
8133                 }
8134                 if (s > 0)
8135                         t = t + s * model->num_surfaces;
8136                 if (t->animated)
8137                 {
8138                         // use an alternate animation if the entity's frame is not 0,
8139                         // and only if the texture has an alternate animation
8140                         if (rsurface.ent_alttextures && t->anim_total[1])
8141                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8142                         else
8143                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8144                 }
8145                 texture->currentframe = t;
8146         }
8147
8148         // update currentskinframe to be a qw skin or animation frame
8149         if (rsurface.ent_qwskin >= 0)
8150         {
8151                 i = rsurface.ent_qwskin;
8152                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8153                 {
8154                         r_qwskincache_size = cl.maxclients;
8155                         if (r_qwskincache)
8156                                 Mem_Free(r_qwskincache);
8157                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8158                 }
8159                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8160                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8161                 t->currentskinframe = r_qwskincache[i].skinframe;
8162                 if (t->currentskinframe == NULL)
8163                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8164         }
8165         else if (t->numskinframes >= 2)
8166                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8167         if (t->backgroundnumskinframes >= 2)
8168                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8169
8170         t->currentmaterialflags = t->basematerialflags;
8171         t->currentalpha = rsurface.colormod[3];
8172         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8173                 t->currentalpha *= r_wateralpha.value;
8174         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8175                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8176         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8177                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8178         if (!(rsurface.ent_flags & RENDER_LIGHT))
8179                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8180         else if (FAKELIGHT_ENABLED)
8181         {
8182                 // no modellight if using fakelight for the map
8183         }
8184         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8185         {
8186                 // pick a model lighting mode
8187                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8188                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8189                 else
8190                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8191         }
8192         if (rsurface.ent_flags & RENDER_ADDITIVE)
8193                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8194         else if (t->currentalpha < 1)
8195                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8196         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8197         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8198                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8199         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8200                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8201         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8202                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8203         if (t->backgroundnumskinframes)
8204                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8205         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8206         {
8207                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8208                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8209         }
8210         else
8211                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8212         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8213         {
8214                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8215                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8216         }
8217         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8218                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8219
8220         // there is no tcmod
8221         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8222         {
8223                 t->currenttexmatrix = r_waterscrollmatrix;
8224                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8225         }
8226         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8227         {
8228                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8229                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8230         }
8231
8232         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8233                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8234         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8235                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8236
8237         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8238         if (t->currentskinframe->qpixels)
8239                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8240         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8241         if (!t->basetexture)
8242                 t->basetexture = r_texture_notexture;
8243         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8244         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8245         t->nmaptexture = t->currentskinframe->nmap;
8246         if (!t->nmaptexture)
8247                 t->nmaptexture = r_texture_blanknormalmap;
8248         t->glosstexture = r_texture_black;
8249         t->glowtexture = t->currentskinframe->glow;
8250         t->fogtexture = t->currentskinframe->fog;
8251         t->reflectmasktexture = t->currentskinframe->reflect;
8252         if (t->backgroundnumskinframes)
8253         {
8254                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8255                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8256                 t->backgroundglosstexture = r_texture_black;
8257                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8258                 if (!t->backgroundnmaptexture)
8259                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8260                 // make sure that if glow is going to be used, both textures are not NULL
8261                 if (!t->backgroundglowtexture && t->glowtexture)
8262                         t->backgroundglowtexture = r_texture_black;
8263                 if (!t->glowtexture && t->backgroundglowtexture)
8264                         t->glowtexture = r_texture_black;
8265         }
8266         else
8267         {
8268                 t->backgroundbasetexture = r_texture_white;
8269                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8270                 t->backgroundglosstexture = r_texture_black;
8271                 t->backgroundglowtexture = NULL;
8272         }
8273         t->specularpower = r_shadow_glossexponent.value;
8274         // TODO: store reference values for these in the texture?
8275         t->specularscale = 0;
8276         if (r_shadow_gloss.integer > 0)
8277         {
8278                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8279                 {
8280                         if (r_shadow_glossintensity.value > 0)
8281                         {
8282                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8283                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8284                                 t->specularscale = r_shadow_glossintensity.value;
8285                         }
8286                 }
8287                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8288                 {
8289                         t->glosstexture = r_texture_white;
8290                         t->backgroundglosstexture = r_texture_white;
8291                         t->specularscale = r_shadow_gloss2intensity.value;
8292                         t->specularpower = r_shadow_gloss2exponent.value;
8293                 }
8294         }
8295         t->specularscale *= t->specularscalemod;
8296         t->specularpower *= t->specularpowermod;
8297         t->rtlightambient = 0;
8298
8299         // lightmaps mode looks bad with dlights using actual texturing, so turn
8300         // off the colormap and glossmap, but leave the normalmap on as it still
8301         // accurately represents the shading involved
8302         if (gl_lightmaps.integer)
8303         {
8304                 t->basetexture = r_texture_grey128;
8305                 t->pantstexture = r_texture_black;
8306                 t->shirttexture = r_texture_black;
8307                 if (gl_lightmaps.integer < 2)
8308                         t->nmaptexture = r_texture_blanknormalmap;
8309                 t->glosstexture = r_texture_black;
8310                 t->glowtexture = NULL;
8311                 t->fogtexture = NULL;
8312                 t->reflectmasktexture = NULL;
8313                 t->backgroundbasetexture = NULL;
8314                 if (gl_lightmaps.integer < 2)
8315                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8316                 t->backgroundglosstexture = r_texture_black;
8317                 t->backgroundglowtexture = NULL;
8318                 t->specularscale = 0;
8319                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8320         }
8321
8322         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8323         VectorClear(t->dlightcolor);
8324         t->currentnumlayers = 0;
8325         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8326         {
8327                 int blendfunc1, blendfunc2;
8328                 qboolean depthmask;
8329                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8330                 {
8331                         blendfunc1 = GL_SRC_ALPHA;
8332                         blendfunc2 = GL_ONE;
8333                 }
8334                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8335                 {
8336                         blendfunc1 = GL_SRC_ALPHA;
8337                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8338                 }
8339                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8340                 {
8341                         blendfunc1 = t->customblendfunc[0];
8342                         blendfunc2 = t->customblendfunc[1];
8343                 }
8344                 else
8345                 {
8346                         blendfunc1 = GL_ONE;
8347                         blendfunc2 = GL_ZERO;
8348                 }
8349                 // don't colormod evilblend textures
8350                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8351                         VectorSet(t->lightmapcolor, 1, 1, 1);
8352                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8353                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8354                 {
8355                         // fullbright is not affected by r_refdef.lightmapintensity
8356                         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]);
8357                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8358                                 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]);
8359                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8360                                 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]);
8361                 }
8362                 else
8363                 {
8364                         vec3_t ambientcolor;
8365                         float colorscale;
8366                         // set the color tint used for lights affecting this surface
8367                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8368                         colorscale = 2;
8369                         // q3bsp has no lightmap updates, so the lightstylevalue that
8370                         // would normally be baked into the lightmap must be
8371                         // applied to the color
8372                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8373                         if (model->type == mod_brushq3)
8374                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8375                         colorscale *= r_refdef.lightmapintensity;
8376                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8377                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8378                         // basic lit geometry
8379                         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]);
8380                         // add pants/shirt if needed
8381                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8382                                 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]);
8383                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8384                                 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]);
8385                         // now add ambient passes if needed
8386                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8387                         {
8388                                 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]);
8389                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8390                                         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]);
8391                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8392                                         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]);
8393                         }
8394                 }
8395                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8396                         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]);
8397                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8398                 {
8399                         // if this is opaque use alpha blend which will darken the earlier
8400                         // passes cheaply.
8401                         //
8402                         // if this is an alpha blended material, all the earlier passes
8403                         // were darkened by fog already, so we only need to add the fog
8404                         // color ontop through the fog mask texture
8405                         //
8406                         // if this is an additive blended material, all the earlier passes
8407                         // were darkened by fog already, and we should not add fog color
8408                         // (because the background was not darkened, there is no fog color
8409                         // that was lost behind it).
8410                         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]);
8411                 }
8412         }
8413
8414         return t->currentframe;
8415 }
8416
8417 rsurfacestate_t rsurface;
8418
8419 void RSurf_ActiveWorldEntity(void)
8420 {
8421         dp_model_t *model = r_refdef.scene.worldmodel;
8422         //if (rsurface.entity == r_refdef.scene.worldentity)
8423         //      return;
8424         rsurface.entity = r_refdef.scene.worldentity;
8425         rsurface.skeleton = NULL;
8426         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8427         rsurface.ent_skinnum = 0;
8428         rsurface.ent_qwskin = -1;
8429         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8430         rsurface.shadertime = r_refdef.scene.time;
8431         rsurface.matrix = identitymatrix;
8432         rsurface.inversematrix = identitymatrix;
8433         rsurface.matrixscale = 1;
8434         rsurface.inversematrixscale = 1;
8435         R_EntityMatrix(&identitymatrix);
8436         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8437         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8438         rsurface.fograngerecip = r_refdef.fograngerecip;
8439         rsurface.fogheightfade = r_refdef.fogheightfade;
8440         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8441         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8442         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8443         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8444         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8445         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8446         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8447         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8448         rsurface.colormod[3] = 1;
8449         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);
8450         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8451         rsurface.frameblend[0].lerp = 1;
8452         rsurface.ent_alttextures = false;
8453         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8454         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8455         rsurface.entityskeletaltransform3x4 = NULL;
8456         rsurface.entityskeletaltransform3x4buffer = NULL;
8457         rsurface.entityskeletaltransform3x4offset = 0;
8458         rsurface.entityskeletaltransform3x4size = 0;;
8459         rsurface.entityskeletalnumtransforms = 0;
8460         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8461         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8462         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8463         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8464         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8465         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8466         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8467         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8468         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8469         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8470         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8471         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8472         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8473         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8475         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8476         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8478         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8479         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8481         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8482         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8484         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8485         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8486         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8487         rsurface.modelelement3i = model->surfmesh.data_element3i;
8488         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8489         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8490         rsurface.modelelement3s = model->surfmesh.data_element3s;
8491         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8492         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8493         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8494         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8495         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8496         rsurface.modelsurfaces = model->data_surfaces;
8497         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8498         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8499         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8500         rsurface.modelgeneratedvertex = false;
8501         rsurface.batchgeneratedvertex = false;
8502         rsurface.batchfirstvertex = 0;
8503         rsurface.batchnumvertices = 0;
8504         rsurface.batchfirsttriangle = 0;
8505         rsurface.batchnumtriangles = 0;
8506         rsurface.batchvertex3f  = NULL;
8507         rsurface.batchvertex3f_vertexbuffer = NULL;
8508         rsurface.batchvertex3f_bufferoffset = 0;
8509         rsurface.batchsvector3f = NULL;
8510         rsurface.batchsvector3f_vertexbuffer = NULL;
8511         rsurface.batchsvector3f_bufferoffset = 0;
8512         rsurface.batchtvector3f = NULL;
8513         rsurface.batchtvector3f_vertexbuffer = NULL;
8514         rsurface.batchtvector3f_bufferoffset = 0;
8515         rsurface.batchnormal3f  = NULL;
8516         rsurface.batchnormal3f_vertexbuffer = NULL;
8517         rsurface.batchnormal3f_bufferoffset = 0;
8518         rsurface.batchlightmapcolor4f = NULL;
8519         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8520         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8521         rsurface.batchtexcoordtexture2f = NULL;
8522         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8523         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8524         rsurface.batchtexcoordlightmap2f = NULL;
8525         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8526         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8527         rsurface.batchskeletalindex4ub = NULL;
8528         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8529         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8530         rsurface.batchskeletalweight4ub = NULL;
8531         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8532         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8533         rsurface.batchvertexmesh = NULL;
8534         rsurface.batchvertexmesh_vertexbuffer = NULL;
8535         rsurface.batchvertexmesh_bufferoffset = 0;
8536         rsurface.batchelement3i = NULL;
8537         rsurface.batchelement3i_indexbuffer = NULL;
8538         rsurface.batchelement3i_bufferoffset = 0;
8539         rsurface.batchelement3s = NULL;
8540         rsurface.batchelement3s_indexbuffer = NULL;
8541         rsurface.batchelement3s_bufferoffset = 0;
8542         rsurface.passcolor4f = NULL;
8543         rsurface.passcolor4f_vertexbuffer = NULL;
8544         rsurface.passcolor4f_bufferoffset = 0;
8545         rsurface.forcecurrenttextureupdate = false;
8546 }
8547
8548 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8549 {
8550         dp_model_t *model = ent->model;
8551         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8552         //      return;
8553         rsurface.entity = (entity_render_t *)ent;
8554         rsurface.skeleton = ent->skeleton;
8555         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8556         rsurface.ent_skinnum = ent->skinnum;
8557         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;
8558         rsurface.ent_flags = ent->flags;
8559         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8560         rsurface.matrix = ent->matrix;
8561         rsurface.inversematrix = ent->inversematrix;
8562         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8563         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8564         R_EntityMatrix(&rsurface.matrix);
8565         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8566         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8567         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8568         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8569         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8570         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8571         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8572         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8573         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8574         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8575         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8576         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8577         rsurface.colormod[3] = ent->alpha;
8578         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8579         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8580         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8581         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8582         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8583         if (ent->model->brush.submodel && !prepass)
8584         {
8585                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8586                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8587         }
8588         // if the animcache code decided it should use the shader path, skip the deform step
8589         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8590         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8591         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8592         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8593         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8594         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8595         {
8596                 if (ent->animcache_vertex3f)
8597                 {
8598                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8599                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8600                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8601                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8602                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8603                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8604                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8605                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8606                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8607                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8608                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8609                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8610                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8611                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8612                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8613                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8614                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8615                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8616                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8617                 }
8618                 else if (wanttangents)
8619                 {
8620                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8621                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8622                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8623                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8624                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8625                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8626                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8627                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8628                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8629                         rsurface.modelvertexmesh = NULL;
8630                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8631                         rsurface.modelvertexmesh_bufferoffset = 0;
8632                         rsurface.modelvertex3f_vertexbuffer = NULL;
8633                         rsurface.modelvertex3f_bufferoffset = 0;
8634                         rsurface.modelvertex3f_vertexbuffer = 0;
8635                         rsurface.modelvertex3f_bufferoffset = 0;
8636                         rsurface.modelsvector3f_vertexbuffer = 0;
8637                         rsurface.modelsvector3f_bufferoffset = 0;
8638                         rsurface.modeltvector3f_vertexbuffer = 0;
8639                         rsurface.modeltvector3f_bufferoffset = 0;
8640                         rsurface.modelnormal3f_vertexbuffer = 0;
8641                         rsurface.modelnormal3f_bufferoffset = 0;
8642                 }
8643                 else if (wantnormals)
8644                 {
8645                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8646                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8647                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8648                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8649                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8650                         rsurface.modelsvector3f = NULL;
8651                         rsurface.modeltvector3f = NULL;
8652                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8653                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8654                         rsurface.modelvertexmesh = NULL;
8655                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8656                         rsurface.modelvertexmesh_bufferoffset = 0;
8657                         rsurface.modelvertex3f_vertexbuffer = NULL;
8658                         rsurface.modelvertex3f_bufferoffset = 0;
8659                         rsurface.modelvertex3f_vertexbuffer = 0;
8660                         rsurface.modelvertex3f_bufferoffset = 0;
8661                         rsurface.modelsvector3f_vertexbuffer = 0;
8662                         rsurface.modelsvector3f_bufferoffset = 0;
8663                         rsurface.modeltvector3f_vertexbuffer = 0;
8664                         rsurface.modeltvector3f_bufferoffset = 0;
8665                         rsurface.modelnormal3f_vertexbuffer = 0;
8666                         rsurface.modelnormal3f_bufferoffset = 0;
8667                 }
8668                 else
8669                 {
8670                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8671                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8672                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8673                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8674                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8675                         rsurface.modelsvector3f = NULL;
8676                         rsurface.modeltvector3f = NULL;
8677                         rsurface.modelnormal3f = NULL;
8678                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8679                         rsurface.modelvertexmesh = NULL;
8680                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8681                         rsurface.modelvertexmesh_bufferoffset = 0;
8682                         rsurface.modelvertex3f_vertexbuffer = NULL;
8683                         rsurface.modelvertex3f_bufferoffset = 0;
8684                         rsurface.modelvertex3f_vertexbuffer = 0;
8685                         rsurface.modelvertex3f_bufferoffset = 0;
8686                         rsurface.modelsvector3f_vertexbuffer = 0;
8687                         rsurface.modelsvector3f_bufferoffset = 0;
8688                         rsurface.modeltvector3f_vertexbuffer = 0;
8689                         rsurface.modeltvector3f_bufferoffset = 0;
8690                         rsurface.modelnormal3f_vertexbuffer = 0;
8691                         rsurface.modelnormal3f_bufferoffset = 0;
8692                 }
8693                 rsurface.modelgeneratedvertex = true;
8694         }
8695         else
8696         {
8697                 if (rsurface.entityskeletaltransform3x4)
8698                 {
8699                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8700                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8701                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8702                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8703                 }
8704                 else
8705                 {
8706                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8707                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8708                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8709                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8710                 }
8711                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8712                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8713                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8714                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8715                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8716                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8717                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8718                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8719                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8720                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8721                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8722                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8723                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8724                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8725                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8726                 rsurface.modelgeneratedvertex = false;
8727         }
8728         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8729         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8730         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8731         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8732         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8733         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8734         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8735         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8736         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8737         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8738         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8739         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8740         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8741         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8742         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8743         rsurface.modelelement3i = model->surfmesh.data_element3i;
8744         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8745         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8746         rsurface.modelelement3s = model->surfmesh.data_element3s;
8747         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8748         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8749         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8750         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8751         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8752         rsurface.modelsurfaces = model->data_surfaces;
8753         rsurface.batchgeneratedvertex = false;
8754         rsurface.batchfirstvertex = 0;
8755         rsurface.batchnumvertices = 0;
8756         rsurface.batchfirsttriangle = 0;
8757         rsurface.batchnumtriangles = 0;
8758         rsurface.batchvertex3f  = NULL;
8759         rsurface.batchvertex3f_vertexbuffer = NULL;
8760         rsurface.batchvertex3f_bufferoffset = 0;
8761         rsurface.batchsvector3f = NULL;
8762         rsurface.batchsvector3f_vertexbuffer = NULL;
8763         rsurface.batchsvector3f_bufferoffset = 0;
8764         rsurface.batchtvector3f = NULL;
8765         rsurface.batchtvector3f_vertexbuffer = NULL;
8766         rsurface.batchtvector3f_bufferoffset = 0;
8767         rsurface.batchnormal3f  = NULL;
8768         rsurface.batchnormal3f_vertexbuffer = NULL;
8769         rsurface.batchnormal3f_bufferoffset = 0;
8770         rsurface.batchlightmapcolor4f = NULL;
8771         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8772         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8773         rsurface.batchtexcoordtexture2f = NULL;
8774         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8775         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8776         rsurface.batchtexcoordlightmap2f = NULL;
8777         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8778         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8779         rsurface.batchskeletalindex4ub = NULL;
8780         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8781         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8782         rsurface.batchskeletalweight4ub = NULL;
8783         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8784         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8785         rsurface.batchvertexmesh = NULL;
8786         rsurface.batchvertexmesh_vertexbuffer = NULL;
8787         rsurface.batchvertexmesh_bufferoffset = 0;
8788         rsurface.batchelement3i = NULL;
8789         rsurface.batchelement3i_indexbuffer = NULL;
8790         rsurface.batchelement3i_bufferoffset = 0;
8791         rsurface.batchelement3s = NULL;
8792         rsurface.batchelement3s_indexbuffer = NULL;
8793         rsurface.batchelement3s_bufferoffset = 0;
8794         rsurface.passcolor4f = NULL;
8795         rsurface.passcolor4f_vertexbuffer = NULL;
8796         rsurface.passcolor4f_bufferoffset = 0;
8797         rsurface.forcecurrenttextureupdate = false;
8798 }
8799
8800 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)
8801 {
8802         rsurface.entity = r_refdef.scene.worldentity;
8803         rsurface.skeleton = NULL;
8804         rsurface.ent_skinnum = 0;
8805         rsurface.ent_qwskin = -1;
8806         rsurface.ent_flags = entflags;
8807         rsurface.shadertime = r_refdef.scene.time - shadertime;
8808         rsurface.modelnumvertices = numvertices;
8809         rsurface.modelnumtriangles = numtriangles;
8810         rsurface.matrix = *matrix;
8811         rsurface.inversematrix = *inversematrix;
8812         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8813         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8814         R_EntityMatrix(&rsurface.matrix);
8815         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8816         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8817         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8818         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8819         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8820         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8821         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8822         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8823         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8824         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8825         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8826         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8827         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);
8828         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8829         rsurface.frameblend[0].lerp = 1;
8830         rsurface.ent_alttextures = false;
8831         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8832         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8833         rsurface.entityskeletaltransform3x4 = NULL;
8834         rsurface.entityskeletaltransform3x4buffer = NULL;
8835         rsurface.entityskeletaltransform3x4offset = 0;
8836         rsurface.entityskeletaltransform3x4size = 0;
8837         rsurface.entityskeletalnumtransforms = 0;
8838         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8839         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8840         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8841         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8842         if (wanttangents)
8843         {
8844                 rsurface.modelvertex3f = (float *)vertex3f;
8845                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8846                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8847                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8848         }
8849         else if (wantnormals)
8850         {
8851                 rsurface.modelvertex3f = (float *)vertex3f;
8852                 rsurface.modelsvector3f = NULL;
8853                 rsurface.modeltvector3f = NULL;
8854                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8855         }
8856         else
8857         {
8858                 rsurface.modelvertex3f = (float *)vertex3f;
8859                 rsurface.modelsvector3f = NULL;
8860                 rsurface.modeltvector3f = NULL;
8861                 rsurface.modelnormal3f = NULL;
8862         }
8863         rsurface.modelvertexmesh = NULL;
8864         rsurface.modelvertexmesh_vertexbuffer = NULL;
8865         rsurface.modelvertexmesh_bufferoffset = 0;
8866         rsurface.modelvertex3f_vertexbuffer = 0;
8867         rsurface.modelvertex3f_bufferoffset = 0;
8868         rsurface.modelsvector3f_vertexbuffer = 0;
8869         rsurface.modelsvector3f_bufferoffset = 0;
8870         rsurface.modeltvector3f_vertexbuffer = 0;
8871         rsurface.modeltvector3f_bufferoffset = 0;
8872         rsurface.modelnormal3f_vertexbuffer = 0;
8873         rsurface.modelnormal3f_bufferoffset = 0;
8874         rsurface.modelgeneratedvertex = true;
8875         rsurface.modellightmapcolor4f  = (float *)color4f;
8876         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8877         rsurface.modellightmapcolor4f_bufferoffset = 0;
8878         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8879         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8880         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8881         rsurface.modeltexcoordlightmap2f  = NULL;
8882         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8883         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8884         rsurface.modelskeletalindex4ub = NULL;
8885         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8886         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8887         rsurface.modelskeletalweight4ub = NULL;
8888         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8889         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8890         rsurface.modelelement3i = (int *)element3i;
8891         rsurface.modelelement3i_indexbuffer = NULL;
8892         rsurface.modelelement3i_bufferoffset = 0;
8893         rsurface.modelelement3s = (unsigned short *)element3s;
8894         rsurface.modelelement3s_indexbuffer = NULL;
8895         rsurface.modelelement3s_bufferoffset = 0;
8896         rsurface.modellightmapoffsets = NULL;
8897         rsurface.modelsurfaces = NULL;
8898         rsurface.batchgeneratedvertex = false;
8899         rsurface.batchfirstvertex = 0;
8900         rsurface.batchnumvertices = 0;
8901         rsurface.batchfirsttriangle = 0;
8902         rsurface.batchnumtriangles = 0;
8903         rsurface.batchvertex3f  = NULL;
8904         rsurface.batchvertex3f_vertexbuffer = NULL;
8905         rsurface.batchvertex3f_bufferoffset = 0;
8906         rsurface.batchsvector3f = NULL;
8907         rsurface.batchsvector3f_vertexbuffer = NULL;
8908         rsurface.batchsvector3f_bufferoffset = 0;
8909         rsurface.batchtvector3f = NULL;
8910         rsurface.batchtvector3f_vertexbuffer = NULL;
8911         rsurface.batchtvector3f_bufferoffset = 0;
8912         rsurface.batchnormal3f  = NULL;
8913         rsurface.batchnormal3f_vertexbuffer = NULL;
8914         rsurface.batchnormal3f_bufferoffset = 0;
8915         rsurface.batchlightmapcolor4f = NULL;
8916         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8917         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8918         rsurface.batchtexcoordtexture2f = NULL;
8919         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8920         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8921         rsurface.batchtexcoordlightmap2f = NULL;
8922         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8923         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8924         rsurface.batchskeletalindex4ub = NULL;
8925         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8926         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8927         rsurface.batchskeletalweight4ub = NULL;
8928         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8929         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8930         rsurface.batchvertexmesh = NULL;
8931         rsurface.batchvertexmesh_vertexbuffer = NULL;
8932         rsurface.batchvertexmesh_bufferoffset = 0;
8933         rsurface.batchelement3i = NULL;
8934         rsurface.batchelement3i_indexbuffer = NULL;
8935         rsurface.batchelement3i_bufferoffset = 0;
8936         rsurface.batchelement3s = NULL;
8937         rsurface.batchelement3s_indexbuffer = NULL;
8938         rsurface.batchelement3s_bufferoffset = 0;
8939         rsurface.passcolor4f = NULL;
8940         rsurface.passcolor4f_vertexbuffer = NULL;
8941         rsurface.passcolor4f_bufferoffset = 0;
8942         rsurface.forcecurrenttextureupdate = true;
8943
8944         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8945         {
8946                 if ((wantnormals || wanttangents) && !normal3f)
8947                 {
8948                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8949                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8950                 }
8951                 if (wanttangents && !svector3f)
8952                 {
8953                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8954                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8955                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8956                 }
8957         }
8958 }
8959
8960 float RSurf_FogPoint(const float *v)
8961 {
8962         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8963         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8964         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8965         float FogHeightFade = r_refdef.fogheightfade;
8966         float fogfrac;
8967         unsigned int fogmasktableindex;
8968         if (r_refdef.fogplaneviewabove)
8969                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8970         else
8971                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8972         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8973         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8974 }
8975
8976 float RSurf_FogVertex(const float *v)
8977 {
8978         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8979         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8980         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8981         float FogHeightFade = rsurface.fogheightfade;
8982         float fogfrac;
8983         unsigned int fogmasktableindex;
8984         if (r_refdef.fogplaneviewabove)
8985                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8986         else
8987                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8988         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8989         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8990 }
8991
8992 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8993 {
8994         int i;
8995         for (i = 0;i < numelements;i++)
8996                 outelement3i[i] = inelement3i[i] + adjust;
8997 }
8998
8999 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9000 extern cvar_t gl_vbo;
9001 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9002 {
9003         int deformindex;
9004         int firsttriangle;
9005         int numtriangles;
9006         int firstvertex;
9007         int endvertex;
9008         int numvertices;
9009         int surfacefirsttriangle;
9010         int surfacenumtriangles;
9011         int surfacefirstvertex;
9012         int surfaceendvertex;
9013         int surfacenumvertices;
9014         int batchnumsurfaces = texturenumsurfaces;
9015         int batchnumvertices;
9016         int batchnumtriangles;
9017         int needsupdate;
9018         int i, j;
9019         qboolean gaps;
9020         qboolean dynamicvertex;
9021         float amplitude;
9022         float animpos;
9023         float scale;
9024         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9025         float waveparms[4];
9026         unsigned char *ub;
9027         q3shaderinfo_deform_t *deform;
9028         const msurface_t *surface, *firstsurface;
9029         r_vertexmesh_t *vertexmesh;
9030         if (!texturenumsurfaces)
9031                 return;
9032         // find vertex range of this surface batch
9033         gaps = false;
9034         firstsurface = texturesurfacelist[0];
9035         firsttriangle = firstsurface->num_firsttriangle;
9036         batchnumvertices = 0;
9037         batchnumtriangles = 0;
9038         firstvertex = endvertex = firstsurface->num_firstvertex;
9039         for (i = 0;i < texturenumsurfaces;i++)
9040         {
9041                 surface = texturesurfacelist[i];
9042                 if (surface != firstsurface + i)
9043                         gaps = true;
9044                 surfacefirstvertex = surface->num_firstvertex;
9045                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9046                 surfacenumvertices = surface->num_vertices;
9047                 surfacenumtriangles = surface->num_triangles;
9048                 if (firstvertex > surfacefirstvertex)
9049                         firstvertex = surfacefirstvertex;
9050                 if (endvertex < surfaceendvertex)
9051                         endvertex = surfaceendvertex;
9052                 batchnumvertices += surfacenumvertices;
9053                 batchnumtriangles += surfacenumtriangles;
9054         }
9055
9056         r_refdef.stats[r_stat_batch_batches]++;
9057         if (gaps)
9058                 r_refdef.stats[r_stat_batch_withgaps]++;
9059         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9060         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9061         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9062
9063         // we now know the vertex range used, and if there are any gaps in it
9064         rsurface.batchfirstvertex = firstvertex;
9065         rsurface.batchnumvertices = endvertex - firstvertex;
9066         rsurface.batchfirsttriangle = firsttriangle;
9067         rsurface.batchnumtriangles = batchnumtriangles;
9068
9069         // this variable holds flags for which properties have been updated that
9070         // may require regenerating vertexmesh array...
9071         needsupdate = 0;
9072
9073         // check if any dynamic vertex processing must occur
9074         dynamicvertex = false;
9075
9076         // a cvar to force the dynamic vertex path to be taken, for debugging
9077         if (r_batch_debugdynamicvertexpath.integer)
9078         {
9079                 if (!dynamicvertex)
9080                 {
9081                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9082                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9083                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9084                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9085                 }
9086                 dynamicvertex = true;
9087         }
9088
9089         // if there is a chance of animated vertex colors, it's a dynamic batch
9090         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9091         {
9092                 if (!dynamicvertex)
9093                 {
9094                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9095                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9096                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9097                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9098                 }
9099                 dynamicvertex = true;
9100                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9101         }
9102
9103         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9104         {
9105                 switch (deform->deform)
9106                 {
9107                 default:
9108                 case Q3DEFORM_PROJECTIONSHADOW:
9109                 case Q3DEFORM_TEXT0:
9110                 case Q3DEFORM_TEXT1:
9111                 case Q3DEFORM_TEXT2:
9112                 case Q3DEFORM_TEXT3:
9113                 case Q3DEFORM_TEXT4:
9114                 case Q3DEFORM_TEXT5:
9115                 case Q3DEFORM_TEXT6:
9116                 case Q3DEFORM_TEXT7:
9117                 case Q3DEFORM_NONE:
9118                         break;
9119                 case Q3DEFORM_AUTOSPRITE:
9120                         if (!dynamicvertex)
9121                         {
9122                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9123                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9124                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9125                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9126                         }
9127                         dynamicvertex = true;
9128                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9129                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9130                         break;
9131                 case Q3DEFORM_AUTOSPRITE2:
9132                         if (!dynamicvertex)
9133                         {
9134                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9135                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9136                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9137                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9138                         }
9139                         dynamicvertex = true;
9140                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9141                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9142                         break;
9143                 case Q3DEFORM_NORMAL:
9144                         if (!dynamicvertex)
9145                         {
9146                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9147                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9148                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9149                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9150                         }
9151                         dynamicvertex = true;
9152                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9153                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9154                         break;
9155                 case Q3DEFORM_WAVE:
9156                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9157                                 break; // if wavefunc is a nop, ignore this transform
9158                         if (!dynamicvertex)
9159                         {
9160                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9161                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9162                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9163                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9164                         }
9165                         dynamicvertex = true;
9166                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9167                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9168                         break;
9169                 case Q3DEFORM_BULGE:
9170                         if (!dynamicvertex)
9171                         {
9172                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9173                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9174                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9175                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9176                         }
9177                         dynamicvertex = true;
9178                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9179                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9180                         break;
9181                 case Q3DEFORM_MOVE:
9182                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9183                                 break; // if wavefunc is a nop, ignore this transform
9184                         if (!dynamicvertex)
9185                         {
9186                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9187                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9188                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9189                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9190                         }
9191                         dynamicvertex = true;
9192                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9193                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9194                         break;
9195                 }
9196         }
9197         switch(rsurface.texture->tcgen.tcgen)
9198         {
9199         default:
9200         case Q3TCGEN_TEXTURE:
9201                 break;
9202         case Q3TCGEN_LIGHTMAP:
9203                 if (!dynamicvertex)
9204                 {
9205                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9206                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9207                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9208                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9209                 }
9210                 dynamicvertex = true;
9211                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9212                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9213                 break;
9214         case Q3TCGEN_VECTOR:
9215                 if (!dynamicvertex)
9216                 {
9217                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9218                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9219                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9220                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9221                 }
9222                 dynamicvertex = true;
9223                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9224                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9225                 break;
9226         case Q3TCGEN_ENVIRONMENT:
9227                 if (!dynamicvertex)
9228                 {
9229                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9230                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9231                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9232                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9233                 }
9234                 dynamicvertex = true;
9235                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9236                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9237                 break;
9238         }
9239         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9240         {
9241                 if (!dynamicvertex)
9242                 {
9243                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9244                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9245                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9246                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9247                 }
9248                 dynamicvertex = true;
9249                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9250                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9251         }
9252
9253         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9254         {
9255                 if (!dynamicvertex)
9256                 {
9257                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9258                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9259                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9260                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9261                 }
9262                 dynamicvertex = true;
9263                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9264         }
9265
9266         // when the model data has no vertex buffer (dynamic mesh), we need to
9267         // eliminate gaps
9268         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9269                 batchneed |= BATCHNEED_NOGAPS;
9270
9271         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9272         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9273         // we ensure this by treating the vertex batch as dynamic...
9274         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9275         {
9276                 if (!dynamicvertex)
9277                 {
9278                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9279                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9280                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9281                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9282                 }
9283                 dynamicvertex = true;
9284         }
9285
9286         if (dynamicvertex)
9287         {
9288                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9289                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9290                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9291                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9292                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9293                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9294                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9295                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9296         }
9297
9298         // if needsupdate, we have to do a dynamic vertex batch for sure
9299         if (needsupdate & batchneed)
9300         {
9301                 if (!dynamicvertex)
9302                 {
9303                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9304                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9305                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9306                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9307                 }
9308                 dynamicvertex = true;
9309         }
9310
9311         // see if we need to build vertexmesh from arrays
9312         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9313         {
9314                 if (!dynamicvertex)
9315                 {
9316                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9317                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9318                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9319                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9320                 }
9321                 dynamicvertex = true;
9322         }
9323
9324         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9325         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9326                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9327
9328         rsurface.batchvertex3f = rsurface.modelvertex3f;
9329         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9330         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9331         rsurface.batchsvector3f = rsurface.modelsvector3f;
9332         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9333         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9334         rsurface.batchtvector3f = rsurface.modeltvector3f;
9335         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9336         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9337         rsurface.batchnormal3f = rsurface.modelnormal3f;
9338         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9339         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9340         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9341         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9342         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9343         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9344         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9345         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9346         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9347         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9348         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9349         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9350         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9351         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9352         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9353         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9354         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9355         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9356         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9357         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9358         rsurface.batchelement3i = rsurface.modelelement3i;
9359         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9360         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9361         rsurface.batchelement3s = rsurface.modelelement3s;
9362         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9363         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9364         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9365         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9366         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9367         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9368         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9369
9370         // if any dynamic vertex processing has to occur in software, we copy the
9371         // entire surface list together before processing to rebase the vertices
9372         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9373         //
9374         // if any gaps exist and we do not have a static vertex buffer, we have to
9375         // copy the surface list together to avoid wasting upload bandwidth on the
9376         // vertices in the gaps.
9377         //
9378         // if gaps exist and we have a static vertex buffer, we can choose whether
9379         // to combine the index buffer ranges into one dynamic index buffer or
9380         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9381         //
9382         // in many cases the batch is reduced to one draw call.
9383
9384         rsurface.batchmultidraw = false;
9385         rsurface.batchmultidrawnumsurfaces = 0;
9386         rsurface.batchmultidrawsurfacelist = NULL;
9387
9388         if (!dynamicvertex)
9389         {
9390                 // static vertex data, just set pointers...
9391                 rsurface.batchgeneratedvertex = false;
9392                 // if there are gaps, we want to build a combined index buffer,
9393                 // otherwise use the original static buffer with an appropriate offset
9394                 if (gaps)
9395                 {
9396                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9397                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9398                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9399                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9400                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9401                         {
9402                                 rsurface.batchmultidraw = true;
9403                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9404                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9405                                 return;
9406                         }
9407                         // build a new triangle elements array for this batch
9408                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9409                         rsurface.batchfirsttriangle = 0;
9410                         numtriangles = 0;
9411                         for (i = 0;i < texturenumsurfaces;i++)
9412                         {
9413                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9414                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9415                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9416                                 numtriangles += surfacenumtriangles;
9417                         }
9418                         rsurface.batchelement3i_indexbuffer = NULL;
9419                         rsurface.batchelement3i_bufferoffset = 0;
9420                         rsurface.batchelement3s = NULL;
9421                         rsurface.batchelement3s_indexbuffer = NULL;
9422                         rsurface.batchelement3s_bufferoffset = 0;
9423                         if (endvertex <= 65536)
9424                         {
9425                                 // make a 16bit (unsigned short) index array if possible
9426                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9427                                 for (i = 0;i < numtriangles*3;i++)
9428                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9429                         }
9430                         // upload buffer data for the copytriangles batch
9431                         if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
9432                         {
9433                                 if (rsurface.batchelement3s)
9434                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
9435                                 else if (rsurface.batchelement3i)
9436                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
9437                         }
9438                 }
9439                 else
9440                 {
9441                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9442                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9443                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9444                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9445                 }
9446                 return;
9447         }
9448
9449         // something needs software processing, do it for real...
9450         // we only directly handle separate array data in this case and then
9451         // generate interleaved data if needed...
9452         rsurface.batchgeneratedvertex = true;
9453         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9454         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9455         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9456         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9457
9458         // now copy the vertex data into a combined array and make an index array
9459         // (this is what Quake3 does all the time)
9460         // we also apply any skeletal animation here that would have been done in
9461         // the vertex shader, because most of the dynamic vertex animation cases
9462         // need actual vertex positions and normals
9463         //if (dynamicvertex)
9464         {
9465                 rsurface.batchvertexmesh = NULL;
9466                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9467                 rsurface.batchvertexmesh_bufferoffset = 0;
9468                 rsurface.batchvertex3f = NULL;
9469                 rsurface.batchvertex3f_vertexbuffer = NULL;
9470                 rsurface.batchvertex3f_bufferoffset = 0;
9471                 rsurface.batchsvector3f = NULL;
9472                 rsurface.batchsvector3f_vertexbuffer = NULL;
9473                 rsurface.batchsvector3f_bufferoffset = 0;
9474                 rsurface.batchtvector3f = NULL;
9475                 rsurface.batchtvector3f_vertexbuffer = NULL;
9476                 rsurface.batchtvector3f_bufferoffset = 0;
9477                 rsurface.batchnormal3f = NULL;
9478                 rsurface.batchnormal3f_vertexbuffer = NULL;
9479                 rsurface.batchnormal3f_bufferoffset = 0;
9480                 rsurface.batchlightmapcolor4f = NULL;
9481                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9482                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9483                 rsurface.batchtexcoordtexture2f = NULL;
9484                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9485                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9486                 rsurface.batchtexcoordlightmap2f = NULL;
9487                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9488                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9489                 rsurface.batchskeletalindex4ub = NULL;
9490                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9491                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9492                 rsurface.batchskeletalweight4ub = NULL;
9493                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9494                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9495                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9496                 rsurface.batchelement3i_indexbuffer = NULL;
9497                 rsurface.batchelement3i_bufferoffset = 0;
9498                 rsurface.batchelement3s = NULL;
9499                 rsurface.batchelement3s_indexbuffer = NULL;
9500                 rsurface.batchelement3s_bufferoffset = 0;
9501                 rsurface.batchskeletaltransform3x4buffer = NULL;
9502                 rsurface.batchskeletaltransform3x4offset = 0;
9503                 rsurface.batchskeletaltransform3x4size = 0;
9504                 // we'll only be setting up certain arrays as needed
9505                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9506                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9507                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9508                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9509                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9510                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9511                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9512                 {
9513                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9514                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9515                 }
9516                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9517                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9518                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9519                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9520                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9521                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9522                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9523                 {
9524                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9525                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9526                 }
9527                 numvertices = 0;
9528                 numtriangles = 0;
9529                 for (i = 0;i < texturenumsurfaces;i++)
9530                 {
9531                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9532                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9533                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9534                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9535                         // copy only the data requested
9536                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9537                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9538                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9539                         {
9540                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9541                                 {
9542                                         if (rsurface.batchvertex3f)
9543                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9544                                         else
9545                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9546                                 }
9547                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9548                                 {
9549                                         if (rsurface.modelnormal3f)
9550                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9551                                         else
9552                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9553                                 }
9554                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9555                                 {
9556                                         if (rsurface.modelsvector3f)
9557                                         {
9558                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9559                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9560                                         }
9561                                         else
9562                                         {
9563                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9564                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9565                                         }
9566                                 }
9567                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9568                                 {
9569                                         if (rsurface.modellightmapcolor4f)
9570                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9571                                         else
9572                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9573                                 }
9574                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9575                                 {
9576                                         if (rsurface.modeltexcoordtexture2f)
9577                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9578                                         else
9579                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9580                                 }
9581                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9582                                 {
9583                                         if (rsurface.modeltexcoordlightmap2f)
9584                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9585                                         else
9586                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9587                                 }
9588                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9589                                 {
9590                                         if (rsurface.modelskeletalindex4ub)
9591                                         {
9592                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9593                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9594                                         }
9595                                         else
9596                                         {
9597                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9598                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9599                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9600                                                 for (j = 0;j < surfacenumvertices;j++)
9601                                                         ub[j*4] = 255;
9602                                         }
9603                                 }
9604                         }
9605                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9606                         numvertices += surfacenumvertices;
9607                         numtriangles += surfacenumtriangles;
9608                 }
9609
9610                 // generate a 16bit index array as well if possible
9611                 // (in general, dynamic batches fit)
9612                 if (numvertices <= 65536)
9613                 {
9614                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9615                         for (i = 0;i < numtriangles*3;i++)
9616                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9617                 }
9618
9619                 // since we've copied everything, the batch now starts at 0
9620                 rsurface.batchfirstvertex = 0;
9621                 rsurface.batchnumvertices = batchnumvertices;
9622                 rsurface.batchfirsttriangle = 0;
9623                 rsurface.batchnumtriangles = batchnumtriangles;
9624         }
9625
9626         // apply skeletal animation that would have been done in the vertex shader
9627         if (rsurface.batchskeletaltransform3x4)
9628         {
9629                 const unsigned char *si;
9630                 const unsigned char *sw;
9631                 const float *t[4];
9632                 const float *b = rsurface.batchskeletaltransform3x4;
9633                 float *vp, *vs, *vt, *vn;
9634                 float w[4];
9635                 float m[3][4], n[3][4];
9636                 float tp[3], ts[3], tt[3], tn[3];
9637                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9638                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9639                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9640                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9641                 si = rsurface.batchskeletalindex4ub;
9642                 sw = rsurface.batchskeletalweight4ub;
9643                 vp = rsurface.batchvertex3f;
9644                 vs = rsurface.batchsvector3f;
9645                 vt = rsurface.batchtvector3f;
9646                 vn = rsurface.batchnormal3f;
9647                 memset(m[0], 0, sizeof(m));
9648                 memset(n[0], 0, sizeof(n));
9649                 for (i = 0;i < batchnumvertices;i++)
9650                 {
9651                         t[0] = b + si[0]*12;
9652                         if (sw[0] == 255)
9653                         {
9654                                 // common case - only one matrix
9655                                 m[0][0] = t[0][ 0];
9656                                 m[0][1] = t[0][ 1];
9657                                 m[0][2] = t[0][ 2];
9658                                 m[0][3] = t[0][ 3];
9659                                 m[1][0] = t[0][ 4];
9660                                 m[1][1] = t[0][ 5];
9661                                 m[1][2] = t[0][ 6];
9662                                 m[1][3] = t[0][ 7];
9663                                 m[2][0] = t[0][ 8];
9664                                 m[2][1] = t[0][ 9];
9665                                 m[2][2] = t[0][10];
9666                                 m[2][3] = t[0][11];
9667                         }
9668                         else if (sw[2] + sw[3])
9669                         {
9670                                 // blend 4 matrices
9671                                 t[1] = b + si[1]*12;
9672                                 t[2] = b + si[2]*12;
9673                                 t[3] = b + si[3]*12;
9674                                 w[0] = sw[0] * (1.0f / 255.0f);
9675                                 w[1] = sw[1] * (1.0f / 255.0f);
9676                                 w[2] = sw[2] * (1.0f / 255.0f);
9677                                 w[3] = sw[3] * (1.0f / 255.0f);
9678                                 // blend the matrices
9679                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9680                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9681                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9682                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9683                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9684                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9685                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9686                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9687                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9688                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9689                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9690                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9691                         }
9692                         else
9693                         {
9694                                 // blend 2 matrices
9695                                 t[1] = b + si[1]*12;
9696                                 w[0] = sw[0] * (1.0f / 255.0f);
9697                                 w[1] = sw[1] * (1.0f / 255.0f);
9698                                 // blend the matrices
9699                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9700                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9701                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9702                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9703                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9704                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9705                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9706                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9707                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9708                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9709                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9710                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9711                         }
9712                         si += 4;
9713                         sw += 4;
9714                         // modify the vertex
9715                         VectorCopy(vp, tp);
9716                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9717                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9718                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9719                         vp += 3;
9720                         if (vn)
9721                         {
9722                                 // the normal transformation matrix is a set of cross products...
9723                                 CrossProduct(m[1], m[2], n[0]);
9724                                 CrossProduct(m[2], m[0], n[1]);
9725                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9726                                 VectorCopy(vn, tn);
9727                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9728                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9729                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9730                                 VectorNormalize(vn);
9731                                 vn += 3;
9732                                 if (vs)
9733                                 {
9734                                         VectorCopy(vs, ts);
9735                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9736                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9737                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9738                                         VectorNormalize(vs);
9739                                         vs += 3;
9740                                         VectorCopy(vt, tt);
9741                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9742                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9743                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9744                                         VectorNormalize(vt);
9745                                         vt += 3;
9746                                 }
9747                         }
9748                 }
9749                 rsurface.batchskeletaltransform3x4 = NULL;
9750                 rsurface.batchskeletalnumtransforms = 0;
9751         }
9752
9753         // q1bsp surfaces rendered in vertex color mode have to have colors
9754         // calculated based on lightstyles
9755         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9756         {
9757                 // generate color arrays for the surfaces in this list
9758                 int c[4];
9759                 int scale;
9760                 int size3;
9761                 const int *offsets;
9762                 const unsigned char *lm;
9763                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9764                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9765                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9766                 numvertices = 0;
9767                 for (i = 0;i < texturenumsurfaces;i++)
9768                 {
9769                         surface = texturesurfacelist[i];
9770                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9771                         surfacenumvertices = surface->num_vertices;
9772                         if (surface->lightmapinfo->samples)
9773                         {
9774                                 for (j = 0;j < surfacenumvertices;j++)
9775                                 {
9776                                         lm = surface->lightmapinfo->samples + offsets[j];
9777                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9778                                         VectorScale(lm, scale, c);
9779                                         if (surface->lightmapinfo->styles[1] != 255)
9780                                         {
9781                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9782                                                 lm += size3;
9783                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9784                                                 VectorMA(c, scale, lm, c);
9785                                                 if (surface->lightmapinfo->styles[2] != 255)
9786                                                 {
9787                                                         lm += size3;
9788                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9789                                                         VectorMA(c, scale, lm, c);
9790                                                         if (surface->lightmapinfo->styles[3] != 255)
9791                                                         {
9792                                                                 lm += size3;
9793                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9794                                                                 VectorMA(c, scale, lm, c);
9795                                                         }
9796                                                 }
9797                                         }
9798                                         c[0] >>= 7;
9799                                         c[1] >>= 7;
9800                                         c[2] >>= 7;
9801                                         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);
9802                                         numvertices++;
9803                                 }
9804                         }
9805                         else
9806                         {
9807                                 for (j = 0;j < surfacenumvertices;j++)
9808                                 {
9809                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9810                                         numvertices++;
9811                                 }
9812                         }
9813                 }
9814         }
9815
9816         // if vertices are deformed (sprite flares and things in maps, possibly
9817         // water waves, bulges and other deformations), modify the copied vertices
9818         // in place
9819         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9820         {
9821                 switch (deform->deform)
9822                 {
9823                 default:
9824                 case Q3DEFORM_PROJECTIONSHADOW:
9825                 case Q3DEFORM_TEXT0:
9826                 case Q3DEFORM_TEXT1:
9827                 case Q3DEFORM_TEXT2:
9828                 case Q3DEFORM_TEXT3:
9829                 case Q3DEFORM_TEXT4:
9830                 case Q3DEFORM_TEXT5:
9831                 case Q3DEFORM_TEXT6:
9832                 case Q3DEFORM_TEXT7:
9833                 case Q3DEFORM_NONE:
9834                         break;
9835                 case Q3DEFORM_AUTOSPRITE:
9836                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9837                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9838                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9839                         VectorNormalize(newforward);
9840                         VectorNormalize(newright);
9841                         VectorNormalize(newup);
9842 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9843 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9844 //                      rsurface.batchvertex3f_bufferoffset = 0;
9845 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9846 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9847 //                      rsurface.batchsvector3f_bufferoffset = 0;
9848 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9849 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9850 //                      rsurface.batchtvector3f_bufferoffset = 0;
9851 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9852 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9853 //                      rsurface.batchnormal3f_bufferoffset = 0;
9854                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9855                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9856                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9857                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9858                                 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);
9859                         // a single autosprite surface can contain multiple sprites...
9860                         for (j = 0;j < batchnumvertices - 3;j += 4)
9861                         {
9862                                 VectorClear(center);
9863                                 for (i = 0;i < 4;i++)
9864                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9865                                 VectorScale(center, 0.25f, center);
9866                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9867                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9868                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9869                                 for (i = 0;i < 4;i++)
9870                                 {
9871                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9872                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9873                                 }
9874                         }
9875                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9876                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9877                         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);
9878                         break;
9879                 case Q3DEFORM_AUTOSPRITE2:
9880                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9881                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9882                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9883                         VectorNormalize(newforward);
9884                         VectorNormalize(newright);
9885                         VectorNormalize(newup);
9886 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9887 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9888 //                      rsurface.batchvertex3f_bufferoffset = 0;
9889                         {
9890                                 const float *v1, *v2;
9891                                 vec3_t start, end;
9892                                 float f, l;
9893                                 struct
9894                                 {
9895                                         float length2;
9896                                         const float *v1;
9897                                         const float *v2;
9898                                 }
9899                                 shortest[2];
9900                                 memset(shortest, 0, sizeof(shortest));
9901                                 // a single autosprite surface can contain multiple sprites...
9902                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9903                                 {
9904                                         VectorClear(center);
9905                                         for (i = 0;i < 4;i++)
9906                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9907                                         VectorScale(center, 0.25f, center);
9908                                         // find the two shortest edges, then use them to define the
9909                                         // axis vectors for rotating around the central axis
9910                                         for (i = 0;i < 6;i++)
9911                                         {
9912                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9913                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9914                                                 l = VectorDistance2(v1, v2);
9915                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9916                                                 if (v1[2] != v2[2])
9917                                                         l += (1.0f / 1024.0f);
9918                                                 if (shortest[0].length2 > l || i == 0)
9919                                                 {
9920                                                         shortest[1] = shortest[0];
9921                                                         shortest[0].length2 = l;
9922                                                         shortest[0].v1 = v1;
9923                                                         shortest[0].v2 = v2;
9924                                                 }
9925                                                 else if (shortest[1].length2 > l || i == 1)
9926                                                 {
9927                                                         shortest[1].length2 = l;
9928                                                         shortest[1].v1 = v1;
9929                                                         shortest[1].v2 = v2;
9930                                                 }
9931                                         }
9932                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9933                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9934                                         // this calculates the right vector from the shortest edge
9935                                         // and the up vector from the edge midpoints
9936                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9937                                         VectorNormalize(right);
9938                                         VectorSubtract(end, start, up);
9939                                         VectorNormalize(up);
9940                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9941                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9942                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9943                                         VectorNegate(forward, forward);
9944                                         VectorReflect(forward, 0, up, forward);
9945                                         VectorNormalize(forward);
9946                                         CrossProduct(up, forward, newright);
9947                                         VectorNormalize(newright);
9948                                         // rotate the quad around the up axis vector, this is made
9949                                         // especially easy by the fact we know the quad is flat,
9950                                         // so we only have to subtract the center position and
9951                                         // measure distance along the right vector, and then
9952                                         // multiply that by the newright vector and add back the
9953                                         // center position
9954                                         // we also need to subtract the old position to undo the
9955                                         // displacement from the center, which we do with a
9956                                         // DotProduct, the subtraction/addition of center is also
9957                                         // optimized into DotProducts here
9958                                         l = DotProduct(right, center);
9959                                         for (i = 0;i < 4;i++)
9960                                         {
9961                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9962                                                 f = DotProduct(right, v1) - l;
9963                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9964                                         }
9965                                 }
9966                         }
9967                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9968                         {
9969 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9970 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9971 //                              rsurface.batchnormal3f_bufferoffset = 0;
9972                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9973                         }
9974                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9975                         {
9976 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9977 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9978 //                              rsurface.batchsvector3f_bufferoffset = 0;
9979 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9980 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9981 //                              rsurface.batchtvector3f_bufferoffset = 0;
9982                                 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);
9983                         }
9984                         break;
9985                 case Q3DEFORM_NORMAL:
9986                         // deform the normals to make reflections wavey
9987                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9988                         rsurface.batchnormal3f_vertexbuffer = NULL;
9989                         rsurface.batchnormal3f_bufferoffset = 0;
9990                         for (j = 0;j < batchnumvertices;j++)
9991                         {
9992                                 float vertex[3];
9993                                 float *normal = rsurface.batchnormal3f + 3*j;
9994                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9995                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9996                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9997                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9998                                 VectorNormalize(normal);
9999                         }
10000                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10001                         {
10002 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10003 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10004 //                              rsurface.batchsvector3f_bufferoffset = 0;
10005 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10006 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10007 //                              rsurface.batchtvector3f_bufferoffset = 0;
10008                                 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);
10009                         }
10010                         break;
10011                 case Q3DEFORM_WAVE:
10012                         // deform vertex array to make wavey water and flags and such
10013                         waveparms[0] = deform->waveparms[0];
10014                         waveparms[1] = deform->waveparms[1];
10015                         waveparms[2] = deform->waveparms[2];
10016                         waveparms[3] = deform->waveparms[3];
10017                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10018                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10019                         // this is how a divisor of vertex influence on deformation
10020                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10021                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10022 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10023 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10024 //                      rsurface.batchvertex3f_bufferoffset = 0;
10025 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10026 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10027 //                      rsurface.batchnormal3f_bufferoffset = 0;
10028                         for (j = 0;j < batchnumvertices;j++)
10029                         {
10030                                 // if the wavefunc depends on time, evaluate it per-vertex
10031                                 if (waveparms[3])
10032                                 {
10033                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10034                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10035                                 }
10036                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10037                         }
10038                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10039                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10040                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10041                         {
10042 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10043 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10044 //                              rsurface.batchsvector3f_bufferoffset = 0;
10045 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10046 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10047 //                              rsurface.batchtvector3f_bufferoffset = 0;
10048                                 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);
10049                         }
10050                         break;
10051                 case Q3DEFORM_BULGE:
10052                         // deform vertex array to make the surface have moving bulges
10053 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10054 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10055 //                      rsurface.batchvertex3f_bufferoffset = 0;
10056 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10057 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10058 //                      rsurface.batchnormal3f_bufferoffset = 0;
10059                         for (j = 0;j < batchnumvertices;j++)
10060                         {
10061                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10062                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10063                         }
10064                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10065                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10066                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10067                         {
10068 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10069 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10070 //                              rsurface.batchsvector3f_bufferoffset = 0;
10071 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10072 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10073 //                              rsurface.batchtvector3f_bufferoffset = 0;
10074                                 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);
10075                         }
10076                         break;
10077                 case Q3DEFORM_MOVE:
10078                         // deform vertex array
10079                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10080                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10081                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10082                         VectorScale(deform->parms, scale, waveparms);
10083 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10084 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10085 //                      rsurface.batchvertex3f_bufferoffset = 0;
10086                         for (j = 0;j < batchnumvertices;j++)
10087                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10088                         break;
10089                 }
10090         }
10091
10092         // generate texcoords based on the chosen texcoord source
10093         switch(rsurface.texture->tcgen.tcgen)
10094         {
10095         default:
10096         case Q3TCGEN_TEXTURE:
10097                 break;
10098         case Q3TCGEN_LIGHTMAP:
10099 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10100 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10101 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10102                 if (rsurface.batchtexcoordlightmap2f)
10103                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10104                 break;
10105         case Q3TCGEN_VECTOR:
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] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10112                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10113                 }
10114                 break;
10115         case Q3TCGEN_ENVIRONMENT:
10116                 // make environment reflections using a spheremap
10117                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10118                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10119                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10120                 for (j = 0;j < batchnumvertices;j++)
10121                 {
10122                         // identical to Q3A's method, but executed in worldspace so
10123                         // carried models can be shiny too
10124
10125                         float viewer[3], d, reflected[3], worldreflected[3];
10126
10127                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10128                         // VectorNormalize(viewer);
10129
10130                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10131
10132                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10133                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10134                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10135                         // note: this is proportinal to viewer, so we can normalize later
10136
10137                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10138                         VectorNormalize(worldreflected);
10139
10140                         // note: this sphere map only uses world x and z!
10141                         // so positive and negative y will LOOK THE SAME.
10142                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10143                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10144                 }
10145                 break;
10146         }
10147         // the only tcmod that needs software vertex processing is turbulent, so
10148         // check for it here and apply the changes if needed
10149         // and we only support that as the first one
10150         // (handling a mixture of turbulent and other tcmods would be problematic
10151         //  without punting it entirely to a software path)
10152         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10153         {
10154                 amplitude = rsurface.texture->tcmods[0].parms[1];
10155                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10156 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10157 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10158 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10159                 for (j = 0;j < batchnumvertices;j++)
10160                 {
10161                         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);
10162                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10163                 }
10164         }
10165
10166         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10167         {
10168                 // convert the modified arrays to vertex structs
10169 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10170 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10171 //              rsurface.batchvertexmesh_bufferoffset = 0;
10172                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10173                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10174                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10175                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10176                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10177                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10178                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10179                 {
10180                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10181                         {
10182                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10183                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10184                         }
10185                 }
10186                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10187                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10188                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10189                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10190                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10191                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10192                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10193                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10194                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10195                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10196                 {
10197                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10198                         {
10199                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10200                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10201                         }
10202                 }
10203         }
10204
10205         // upload buffer data for the dynamic batch
10206         if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
10207         {
10208                 if (rsurface.batchvertexmesh)
10209                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset, !vid.forcevbo);
10210                 else
10211                 {
10212                         if (rsurface.batchvertex3f)
10213                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset, !vid.forcevbo);
10214                         if (rsurface.batchsvector3f)
10215                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset, !vid.forcevbo);
10216                         if (rsurface.batchtvector3f)
10217                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset, !vid.forcevbo);
10218                         if (rsurface.batchnormal3f)
10219                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset, !vid.forcevbo);
10220                         if (rsurface.batchlightmapcolor4f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10221                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset, !vid.forcevbo);
10222                         if (rsurface.batchtexcoordtexture2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10223                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset, !vid.forcevbo);
10224                         if (rsurface.batchtexcoordlightmap2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10225                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset, !vid.forcevbo);
10226                         if (rsurface.batchskeletalindex4ub)
10227                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset, !vid.forcevbo);
10228                         if (rsurface.batchskeletalweight4ub)
10229                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset, !vid.forcevbo);
10230                 }
10231                 if (rsurface.batchelement3s)
10232                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
10233                 else if (rsurface.batchelement3i)
10234                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
10235         }
10236 }
10237
10238 void RSurf_DrawBatch(void)
10239 {
10240         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10241         // through the pipeline, killing it earlier in the pipeline would have
10242         // per-surface overhead rather than per-batch overhead, so it's best to
10243         // reject it here, before it hits glDraw.
10244         if (rsurface.batchnumtriangles == 0)
10245                 return;
10246 #if 0
10247         // batch debugging code
10248         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10249         {
10250                 int i;
10251                 int j;
10252                 int c;
10253                 const int *e;
10254                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10255                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10256                 {
10257                         c = e[i];
10258                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10259                         {
10260                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10261                                 {
10262                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10263                                                 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);
10264                                         break;
10265                                 }
10266                         }
10267                 }
10268         }
10269 #endif
10270         if (rsurface.batchmultidraw)
10271         {
10272                 // issue multiple draws rather than copying index data
10273                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10274                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10275                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10276                 for (i = 0;i < numsurfaces;)
10277                 {
10278                         // combine consecutive surfaces as one draw
10279                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10280                                 if (surfacelist[j] != surfacelist[k] + 1)
10281                                         break;
10282                         firstvertex = surfacelist[i]->num_firstvertex;
10283                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10284                         firsttriangle = surfacelist[i]->num_firsttriangle;
10285                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10286                         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);
10287                         i = j;
10288                 }
10289         }
10290         else
10291         {
10292                 // there is only one consecutive run of index data (may have been combined)
10293                 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);
10294         }
10295 }
10296
10297 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10298 {
10299         // pick the closest matching water plane
10300         int planeindex, vertexindex, bestplaneindex = -1;
10301         float d, bestd;
10302         vec3_t vert;
10303         const float *v;
10304         r_waterstate_waterplane_t *p;
10305         qboolean prepared = false;
10306         bestd = 0;
10307         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10308         {
10309                 if(p->camera_entity != rsurface.texture->camera_entity)
10310                         continue;
10311                 d = 0;
10312                 if(!prepared)
10313                 {
10314                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10315                         prepared = true;
10316                         if(rsurface.batchnumvertices == 0)
10317                                 break;
10318                 }
10319                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10320                 {
10321                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10322                         d += fabs(PlaneDiff(vert, &p->plane));
10323                 }
10324                 if (bestd > d || bestplaneindex < 0)
10325                 {
10326                         bestd = d;
10327                         bestplaneindex = planeindex;
10328                 }
10329         }
10330         return bestplaneindex;
10331         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10332         // this situation though, as it might be better to render single larger
10333         // batches with useless stuff (backface culled for example) than to
10334         // render multiple smaller batches
10335 }
10336
10337 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10338 {
10339         int i;
10340         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10341         rsurface.passcolor4f_vertexbuffer = 0;
10342         rsurface.passcolor4f_bufferoffset = 0;
10343         for (i = 0;i < rsurface.batchnumvertices;i++)
10344                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10345 }
10346
10347 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10348 {
10349         int i;
10350         float f;
10351         const float *v;
10352         const float *c;
10353         float *c2;
10354         if (rsurface.passcolor4f)
10355         {
10356                 // generate color arrays
10357                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10358                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10359                 rsurface.passcolor4f_vertexbuffer = 0;
10360                 rsurface.passcolor4f_bufferoffset = 0;
10361                 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)
10362                 {
10363                         f = RSurf_FogVertex(v);
10364                         c2[0] = c[0] * f;
10365                         c2[1] = c[1] * f;
10366                         c2[2] = c[2] * f;
10367                         c2[3] = c[3];
10368                 }
10369         }
10370         else
10371         {
10372                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10373                 rsurface.passcolor4f_vertexbuffer = 0;
10374                 rsurface.passcolor4f_bufferoffset = 0;
10375                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10376                 {
10377                         f = RSurf_FogVertex(v);
10378                         c2[0] = f;
10379                         c2[1] = f;
10380                         c2[2] = f;
10381                         c2[3] = 1;
10382                 }
10383         }
10384 }
10385
10386 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10387 {
10388         int i;
10389         float f;
10390         const float *v;
10391         const float *c;
10392         float *c2;
10393         if (!rsurface.passcolor4f)
10394                 return;
10395         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10396         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10397         rsurface.passcolor4f_vertexbuffer = 0;
10398         rsurface.passcolor4f_bufferoffset = 0;
10399         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)
10400         {
10401                 f = RSurf_FogVertex(v);
10402                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10403                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10404                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10405                 c2[3] = c[3];
10406         }
10407 }
10408
10409 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10410 {
10411         int i;
10412         const float *c;
10413         float *c2;
10414         if (!rsurface.passcolor4f)
10415                 return;
10416         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10417         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10418         rsurface.passcolor4f_vertexbuffer = 0;
10419         rsurface.passcolor4f_bufferoffset = 0;
10420         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10421         {
10422                 c2[0] = c[0] * r;
10423                 c2[1] = c[1] * g;
10424                 c2[2] = c[2] * b;
10425                 c2[3] = c[3] * a;
10426         }
10427 }
10428
10429 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10430 {
10431         int i;
10432         const float *c;
10433         float *c2;
10434         if (!rsurface.passcolor4f)
10435                 return;
10436         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10437         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10438         rsurface.passcolor4f_vertexbuffer = 0;
10439         rsurface.passcolor4f_bufferoffset = 0;
10440         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10441         {
10442                 c2[0] = c[0] + r_refdef.scene.ambient;
10443                 c2[1] = c[1] + r_refdef.scene.ambient;
10444                 c2[2] = c[2] + r_refdef.scene.ambient;
10445                 c2[3] = c[3];
10446         }
10447 }
10448
10449 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10450 {
10451         // TODO: optimize
10452         rsurface.passcolor4f = NULL;
10453         rsurface.passcolor4f_vertexbuffer = 0;
10454         rsurface.passcolor4f_bufferoffset = 0;
10455         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10456         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10457         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10458         GL_Color(r, g, b, a);
10459         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10460         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10461         R_Mesh_TexMatrix(0, NULL);
10462         RSurf_DrawBatch();
10463 }
10464
10465 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10466 {
10467         // TODO: optimize applyfog && applycolor case
10468         // just apply fog if necessary, and tint the fog color array if necessary
10469         rsurface.passcolor4f = NULL;
10470         rsurface.passcolor4f_vertexbuffer = 0;
10471         rsurface.passcolor4f_bufferoffset = 0;
10472         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10473         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10474         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10475         GL_Color(r, g, b, a);
10476         RSurf_DrawBatch();
10477 }
10478
10479 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10480 {
10481         // TODO: optimize
10482         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10483         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10484         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10485         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10486         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10487         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10488         GL_Color(r, g, b, a);
10489         RSurf_DrawBatch();
10490 }
10491
10492 static void RSurf_DrawBatch_GL11_ClampColor(void)
10493 {
10494         int i;
10495         const float *c1;
10496         float *c2;
10497         if (!rsurface.passcolor4f)
10498                 return;
10499         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10500         {
10501                 c2[0] = bound(0.0f, c1[0], 1.0f);
10502                 c2[1] = bound(0.0f, c1[1], 1.0f);
10503                 c2[2] = bound(0.0f, c1[2], 1.0f);
10504                 c2[3] = bound(0.0f, c1[3], 1.0f);
10505         }
10506 }
10507
10508 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10509 {
10510         int i;
10511         float f;
10512         const float *v;
10513         const float *n;
10514         float *c;
10515         //vec3_t eyedir;
10516
10517         // fake shading
10518         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10519         rsurface.passcolor4f_vertexbuffer = 0;
10520         rsurface.passcolor4f_bufferoffset = 0;
10521         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)
10522         {
10523                 f = -DotProduct(r_refdef.view.forward, n);
10524                 f = max(0, f);
10525                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10526                 f *= r_refdef.lightmapintensity;
10527                 Vector4Set(c, f, f, f, 1);
10528         }
10529 }
10530
10531 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10532 {
10533         RSurf_DrawBatch_GL11_ApplyFakeLight();
10534         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10535         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10536         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10537         GL_Color(r, g, b, a);
10538         RSurf_DrawBatch();
10539 }
10540
10541 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10542 {
10543         int i;
10544         float f;
10545         float alpha;
10546         const float *v;
10547         const float *n;
10548         float *c;
10549         vec3_t ambientcolor;
10550         vec3_t diffusecolor;
10551         vec3_t lightdir;
10552         // TODO: optimize
10553         // model lighting
10554         VectorCopy(rsurface.modellight_lightdir, lightdir);
10555         f = 0.5f * r_refdef.lightmapintensity;
10556         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10557         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10558         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10559         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10560         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10561         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10562         alpha = *a;
10563         if (VectorLength2(diffusecolor) > 0)
10564         {
10565                 // q3-style directional shading
10566                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10567                 rsurface.passcolor4f_vertexbuffer = 0;
10568                 rsurface.passcolor4f_bufferoffset = 0;
10569                 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)
10570                 {
10571                         if ((f = DotProduct(n, lightdir)) > 0)
10572                                 VectorMA(ambientcolor, f, diffusecolor, c);
10573                         else
10574                                 VectorCopy(ambientcolor, c);
10575                         c[3] = alpha;
10576                 }
10577                 *r = 1;
10578                 *g = 1;
10579                 *b = 1;
10580                 *a = 1;
10581                 *applycolor = false;
10582         }
10583         else
10584         {
10585                 *r = ambientcolor[0];
10586                 *g = ambientcolor[1];
10587                 *b = ambientcolor[2];
10588                 rsurface.passcolor4f = NULL;
10589                 rsurface.passcolor4f_vertexbuffer = 0;
10590                 rsurface.passcolor4f_bufferoffset = 0;
10591         }
10592 }
10593
10594 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10595 {
10596         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10597         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10598         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10599         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10600         GL_Color(r, g, b, a);
10601         RSurf_DrawBatch();
10602 }
10603
10604 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10605 {
10606         int i;
10607         float f;
10608         const float *v;
10609         float *c;
10610
10611         // fake shading
10612         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10613         rsurface.passcolor4f_vertexbuffer = 0;
10614         rsurface.passcolor4f_bufferoffset = 0;
10615
10616         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10617         {
10618                 f = 1 - RSurf_FogVertex(v);
10619                 c[0] = r;
10620                 c[1] = g;
10621                 c[2] = b;
10622                 c[3] = f * a;
10623         }
10624 }
10625
10626 void RSurf_SetupDepthAndCulling(void)
10627 {
10628         // submodels are biased to avoid z-fighting with world surfaces that they
10629         // may be exactly overlapping (avoids z-fighting artifacts on certain
10630         // doors and things in Quake maps)
10631         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10632         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10633         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10634         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10635 }
10636
10637 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10638 {
10639         // transparent sky would be ridiculous
10640         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10641                 return;
10642         R_SetupShader_Generic_NoTexture(false, false);
10643         skyrenderlater = true;
10644         RSurf_SetupDepthAndCulling();
10645         GL_DepthMask(true);
10646         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10647         // skymasking on them, and Quake3 never did sky masking (unlike
10648         // software Quake and software Quake2), so disable the sky masking
10649         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10650         // and skymasking also looks very bad when noclipping outside the
10651         // level, so don't use it then either.
10652         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10653         {
10654                 R_Mesh_ResetTextureState();
10655                 if (skyrendermasked)
10656                 {
10657                         R_SetupShader_DepthOrShadow(false, false, false);
10658                         // depth-only (masking)
10659                         GL_ColorMask(0,0,0,0);
10660                         // just to make sure that braindead drivers don't draw
10661                         // anything despite that colormask...
10662                         GL_BlendFunc(GL_ZERO, GL_ONE);
10663                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10664                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10665                 }
10666                 else
10667                 {
10668                         R_SetupShader_Generic_NoTexture(false, false);
10669                         // fog sky
10670                         GL_BlendFunc(GL_ONE, GL_ZERO);
10671                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10672                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10673                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10674                 }
10675                 RSurf_DrawBatch();
10676                 if (skyrendermasked)
10677                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10678         }
10679         R_Mesh_ResetTextureState();
10680         GL_Color(1, 1, 1, 1);
10681 }
10682
10683 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10684 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10685 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10686 {
10687         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10688                 return;
10689         if (prepass)
10690         {
10691                 // render screenspace normalmap to texture
10692                 GL_DepthMask(true);
10693                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10694                 RSurf_DrawBatch();
10695                 return;
10696         }
10697
10698         // bind lightmap texture
10699
10700         // water/refraction/reflection/camera surfaces have to be handled specially
10701         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10702         {
10703                 int start, end, startplaneindex;
10704                 for (start = 0;start < texturenumsurfaces;start = end)
10705                 {
10706                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10707                         if(startplaneindex < 0)
10708                         {
10709                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10710                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10711                                 end = start + 1;
10712                                 continue;
10713                         }
10714                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10715                                 ;
10716                         // now that we have a batch using the same planeindex, render it
10717                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10718                         {
10719                                 // render water or distortion background
10720                                 GL_DepthMask(true);
10721                                 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);
10722                                 RSurf_DrawBatch();
10723                                 // blend surface on top
10724                                 GL_DepthMask(false);
10725                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10726                                 RSurf_DrawBatch();
10727                         }
10728                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10729                         {
10730                                 // render surface with reflection texture as input
10731                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10732                                 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);
10733                                 RSurf_DrawBatch();
10734                         }
10735                 }
10736                 return;
10737         }
10738
10739         // render surface batch normally
10740         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10741         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);
10742         RSurf_DrawBatch();
10743 }
10744
10745 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10746 {
10747         // OpenGL 1.3 path - anything not completely ancient
10748         qboolean applycolor;
10749         qboolean applyfog;
10750         int layerindex;
10751         const texturelayer_t *layer;
10752         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);
10753         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10754
10755         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10756         {
10757                 vec4_t layercolor;
10758                 int layertexrgbscale;
10759                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10760                 {
10761                         if (layerindex == 0)
10762                                 GL_AlphaTest(true);
10763                         else
10764                         {
10765                                 GL_AlphaTest(false);
10766                                 GL_DepthFunc(GL_EQUAL);
10767                         }
10768                 }
10769                 GL_DepthMask(layer->depthmask && writedepth);
10770                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10771                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10772                 {
10773                         layertexrgbscale = 4;
10774                         VectorScale(layer->color, 0.25f, layercolor);
10775                 }
10776                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10777                 {
10778                         layertexrgbscale = 2;
10779                         VectorScale(layer->color, 0.5f, layercolor);
10780                 }
10781                 else
10782                 {
10783                         layertexrgbscale = 1;
10784                         VectorScale(layer->color, 1.0f, layercolor);
10785                 }
10786                 layercolor[3] = layer->color[3];
10787                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10788                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10789                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10790                 switch (layer->type)
10791                 {
10792                 case TEXTURELAYERTYPE_LITTEXTURE:
10793                         // single-pass lightmapped texture with 2x rgbscale
10794                         R_Mesh_TexBind(0, r_texture_white);
10795                         R_Mesh_TexMatrix(0, NULL);
10796                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10797                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10798                         R_Mesh_TexBind(1, layer->texture);
10799                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10800                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10801                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10802                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10803                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10804                         else if (FAKELIGHT_ENABLED)
10805                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10806                         else if (rsurface.uselightmaptexture)
10807                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10808                         else
10809                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10810                         break;
10811                 case TEXTURELAYERTYPE_TEXTURE:
10812                         // singletexture unlit texture with transparency support
10813                         R_Mesh_TexBind(0, layer->texture);
10814                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10815                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10816                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10817                         R_Mesh_TexBind(1, 0);
10818                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10819                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10820                         break;
10821                 case TEXTURELAYERTYPE_FOG:
10822                         // singletexture fogging
10823                         if (layer->texture)
10824                         {
10825                                 R_Mesh_TexBind(0, layer->texture);
10826                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10827                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10828                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10829                         }
10830                         else
10831                         {
10832                                 R_Mesh_TexBind(0, 0);
10833                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10834                         }
10835                         R_Mesh_TexBind(1, 0);
10836                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10837                         // generate a color array for the fog pass
10838                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10839                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10840                         RSurf_DrawBatch();
10841                         break;
10842                 default:
10843                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10844                 }
10845         }
10846         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10847         {
10848                 GL_DepthFunc(GL_LEQUAL);
10849                 GL_AlphaTest(false);
10850         }
10851 }
10852
10853 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10854 {
10855         // OpenGL 1.1 - crusty old voodoo path
10856         qboolean applyfog;
10857         int layerindex;
10858         const texturelayer_t *layer;
10859         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);
10860         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10861
10862         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10863         {
10864                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10865                 {
10866                         if (layerindex == 0)
10867                                 GL_AlphaTest(true);
10868                         else
10869                         {
10870                                 GL_AlphaTest(false);
10871                                 GL_DepthFunc(GL_EQUAL);
10872                         }
10873                 }
10874                 GL_DepthMask(layer->depthmask && writedepth);
10875                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10876                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10877                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10878                 switch (layer->type)
10879                 {
10880                 case TEXTURELAYERTYPE_LITTEXTURE:
10881                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10882                         {
10883                                 // two-pass lit texture with 2x rgbscale
10884                                 // first the lightmap pass
10885                                 R_Mesh_TexBind(0, r_texture_white);
10886                                 R_Mesh_TexMatrix(0, NULL);
10887                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10888                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10889                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10890                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10891                                 else if (FAKELIGHT_ENABLED)
10892                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10893                                 else if (rsurface.uselightmaptexture)
10894                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10895                                 else
10896                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10897                                 // then apply the texture to it
10898                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10899                                 R_Mesh_TexBind(0, layer->texture);
10900                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10901                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10902                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10903                                 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);
10904                         }
10905                         else
10906                         {
10907                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10908                                 R_Mesh_TexBind(0, layer->texture);
10909                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10910                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10911                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10912                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10913                                         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);
10914                                 else if (FAKELIGHT_ENABLED)
10915                                         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);
10916                                 else
10917                                         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);
10918                         }
10919                         break;
10920                 case TEXTURELAYERTYPE_TEXTURE:
10921                         // singletexture unlit texture with transparency support
10922                         R_Mesh_TexBind(0, layer->texture);
10923                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10924                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10925                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10926                         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);
10927                         break;
10928                 case TEXTURELAYERTYPE_FOG:
10929                         // singletexture fogging
10930                         if (layer->texture)
10931                         {
10932                                 R_Mesh_TexBind(0, layer->texture);
10933                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10934                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10935                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10936                         }
10937                         else
10938                         {
10939                                 R_Mesh_TexBind(0, 0);
10940                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10941                         }
10942                         // generate a color array for the fog pass
10943                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10944                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10945                         RSurf_DrawBatch();
10946                         break;
10947                 default:
10948                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10949                 }
10950         }
10951         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10952         {
10953                 GL_DepthFunc(GL_LEQUAL);
10954                 GL_AlphaTest(false);
10955         }
10956 }
10957
10958 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10959 {
10960         int vi;
10961         int j;
10962         r_vertexgeneric_t *batchvertex;
10963         float c[4];
10964
10965 //      R_Mesh_ResetTextureState();
10966         R_SetupShader_Generic_NoTexture(false, false);
10967
10968         if(rsurface.texture && rsurface.texture->currentskinframe)
10969         {
10970                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10971                 c[3] *= rsurface.texture->currentalpha;
10972         }
10973         else
10974         {
10975                 c[0] = 1;
10976                 c[1] = 0;
10977                 c[2] = 1;
10978                 c[3] = 1;
10979         }
10980
10981         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10982         {
10983                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10984                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10985                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10986         }
10987
10988         // brighten it up (as texture value 127 means "unlit")
10989         c[0] *= 2 * r_refdef.view.colorscale;
10990         c[1] *= 2 * r_refdef.view.colorscale;
10991         c[2] *= 2 * r_refdef.view.colorscale;
10992
10993         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10994                 c[3] *= r_wateralpha.value;
10995
10996         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10997         {
10998                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10999                 GL_DepthMask(false);
11000         }
11001         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11002         {
11003                 GL_BlendFunc(GL_ONE, GL_ONE);
11004                 GL_DepthMask(false);
11005         }
11006         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11007         {
11008                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11009                 GL_DepthMask(false);
11010         }
11011         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11012         {
11013                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11014                 GL_DepthMask(false);
11015         }
11016         else
11017         {
11018                 GL_BlendFunc(GL_ONE, GL_ZERO);
11019                 GL_DepthMask(writedepth);
11020         }
11021
11022         if (r_showsurfaces.integer == 3)
11023         {
11024                 rsurface.passcolor4f = NULL;
11025
11026                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11027                 {
11028                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11029
11030                         rsurface.passcolor4f = NULL;
11031                         rsurface.passcolor4f_vertexbuffer = 0;
11032                         rsurface.passcolor4f_bufferoffset = 0;
11033                 }
11034                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11035                 {
11036                         qboolean applycolor = true;
11037                         float one = 1.0;
11038
11039                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11040
11041                         r_refdef.lightmapintensity = 1;
11042                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11043                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11044                 }
11045                 else if (FAKELIGHT_ENABLED)
11046                 {
11047                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11048
11049                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11050                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11051                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11052                 }
11053                 else
11054                 {
11055                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11056
11057                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11058                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11059                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11060                 }
11061
11062                 if(!rsurface.passcolor4f)
11063                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11064
11065                 RSurf_DrawBatch_GL11_ApplyAmbient();
11066                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11067                 if(r_refdef.fogenabled)
11068                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11069                 RSurf_DrawBatch_GL11_ClampColor();
11070
11071                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11072                 R_SetupShader_Generic_NoTexture(false, false);
11073                 RSurf_DrawBatch();
11074         }
11075         else if (!r_refdef.view.showdebug)
11076         {
11077                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11078                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11079                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11080                 {
11081                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11082                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11083                 }
11084                 R_Mesh_PrepareVertices_Generic_Unlock();
11085                 RSurf_DrawBatch();
11086         }
11087         else if (r_showsurfaces.integer == 4)
11088         {
11089                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11090                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11091                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11092                 {
11093                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11094                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11095                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11096                 }
11097                 R_Mesh_PrepareVertices_Generic_Unlock();
11098                 RSurf_DrawBatch();
11099         }
11100         else if (r_showsurfaces.integer == 2)
11101         {
11102                 const int *e;
11103                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11104                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11105                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11106                 {
11107                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11108                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11109                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11110                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11111                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11112                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11113                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11114                 }
11115                 R_Mesh_PrepareVertices_Generic_Unlock();
11116                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11117         }
11118         else
11119         {
11120                 int texturesurfaceindex;
11121                 int k;
11122                 const msurface_t *surface;
11123                 float surfacecolor4f[4];
11124                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11125                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11126                 vi = 0;
11127                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11128                 {
11129                         surface = texturesurfacelist[texturesurfaceindex];
11130                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11131                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11132                         for (j = 0;j < surface->num_vertices;j++)
11133                         {
11134                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11135                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11136                                 vi++;
11137                         }
11138                 }
11139                 R_Mesh_PrepareVertices_Generic_Unlock();
11140                 RSurf_DrawBatch();
11141         }
11142 }
11143
11144 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11145 {
11146         CHECKGLERROR
11147         RSurf_SetupDepthAndCulling();
11148         if (r_showsurfaces.integer)
11149         {
11150                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11151                 return;
11152         }
11153         switch (vid.renderpath)
11154         {
11155         case RENDERPATH_GL20:
11156         case RENDERPATH_D3D9:
11157         case RENDERPATH_D3D10:
11158         case RENDERPATH_D3D11:
11159         case RENDERPATH_SOFT:
11160         case RENDERPATH_GLES2:
11161                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11162                 break;
11163         case RENDERPATH_GL13:
11164         case RENDERPATH_GLES1:
11165                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11166                 break;
11167         case RENDERPATH_GL11:
11168                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11169                 break;
11170         }
11171         CHECKGLERROR
11172 }
11173
11174 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11175 {
11176         CHECKGLERROR
11177         RSurf_SetupDepthAndCulling();
11178         if (r_showsurfaces.integer)
11179         {
11180                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11181                 return;
11182         }
11183         switch (vid.renderpath)
11184         {
11185         case RENDERPATH_GL20:
11186         case RENDERPATH_D3D9:
11187         case RENDERPATH_D3D10:
11188         case RENDERPATH_D3D11:
11189         case RENDERPATH_SOFT:
11190         case RENDERPATH_GLES2:
11191                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11192                 break;
11193         case RENDERPATH_GL13:
11194         case RENDERPATH_GLES1:
11195                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11196                 break;
11197         case RENDERPATH_GL11:
11198                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11199                 break;
11200         }
11201         CHECKGLERROR
11202 }
11203
11204 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11205 {
11206         int i, j;
11207         int texturenumsurfaces, endsurface;
11208         texture_t *texture;
11209         const msurface_t *surface;
11210         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11211
11212         // if the model is static it doesn't matter what value we give for
11213         // wantnormals and wanttangents, so this logic uses only rules applicable
11214         // to a model, knowing that they are meaningless otherwise
11215         if (ent == r_refdef.scene.worldentity)
11216                 RSurf_ActiveWorldEntity();
11217         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11218                 RSurf_ActiveModelEntity(ent, false, false, false);
11219         else
11220         {
11221                 switch (vid.renderpath)
11222                 {
11223                 case RENDERPATH_GL20:
11224                 case RENDERPATH_D3D9:
11225                 case RENDERPATH_D3D10:
11226                 case RENDERPATH_D3D11:
11227                 case RENDERPATH_SOFT:
11228                 case RENDERPATH_GLES2:
11229                         RSurf_ActiveModelEntity(ent, true, true, false);
11230                         break;
11231                 case RENDERPATH_GL11:
11232                 case RENDERPATH_GL13:
11233                 case RENDERPATH_GLES1:
11234                         RSurf_ActiveModelEntity(ent, true, false, false);
11235                         break;
11236                 }
11237         }
11238
11239         if (r_transparentdepthmasking.integer)
11240         {
11241                 qboolean setup = false;
11242                 for (i = 0;i < numsurfaces;i = j)
11243                 {
11244                         j = i + 1;
11245                         surface = rsurface.modelsurfaces + surfacelist[i];
11246                         texture = surface->texture;
11247                         rsurface.texture = R_GetCurrentTexture(texture);
11248                         rsurface.lightmaptexture = NULL;
11249                         rsurface.deluxemaptexture = NULL;
11250                         rsurface.uselightmaptexture = false;
11251                         // scan ahead until we find a different texture
11252                         endsurface = min(i + 1024, numsurfaces);
11253                         texturenumsurfaces = 0;
11254                         texturesurfacelist[texturenumsurfaces++] = surface;
11255                         for (;j < endsurface;j++)
11256                         {
11257                                 surface = rsurface.modelsurfaces + surfacelist[j];
11258                                 if (texture != surface->texture)
11259                                         break;
11260                                 texturesurfacelist[texturenumsurfaces++] = surface;
11261                         }
11262                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11263                                 continue;
11264                         // render the range of surfaces as depth
11265                         if (!setup)
11266                         {
11267                                 setup = true;
11268                                 GL_ColorMask(0,0,0,0);
11269                                 GL_Color(1,1,1,1);
11270                                 GL_DepthTest(true);
11271                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11272                                 GL_DepthMask(true);
11273 //                              R_Mesh_ResetTextureState();
11274                         }
11275                         RSurf_SetupDepthAndCulling();
11276                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11277                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11278                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11279                         RSurf_DrawBatch();
11280                 }
11281                 if (setup)
11282                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11283         }
11284
11285         for (i = 0;i < numsurfaces;i = j)
11286         {
11287                 j = i + 1;
11288                 surface = rsurface.modelsurfaces + surfacelist[i];
11289                 texture = surface->texture;
11290                 rsurface.texture = R_GetCurrentTexture(texture);
11291                 // scan ahead until we find a different texture
11292                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11293                 texturenumsurfaces = 0;
11294                 texturesurfacelist[texturenumsurfaces++] = surface;
11295                 if(FAKELIGHT_ENABLED)
11296                 {
11297                         rsurface.lightmaptexture = NULL;
11298                         rsurface.deluxemaptexture = NULL;
11299                         rsurface.uselightmaptexture = false;
11300                         for (;j < endsurface;j++)
11301                         {
11302                                 surface = rsurface.modelsurfaces + surfacelist[j];
11303                                 if (texture != surface->texture)
11304                                         break;
11305                                 texturesurfacelist[texturenumsurfaces++] = surface;
11306                         }
11307                 }
11308                 else
11309                 {
11310                         rsurface.lightmaptexture = surface->lightmaptexture;
11311                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11312                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11313                         for (;j < endsurface;j++)
11314                         {
11315                                 surface = rsurface.modelsurfaces + surfacelist[j];
11316                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11317                                         break;
11318                                 texturesurfacelist[texturenumsurfaces++] = surface;
11319                         }
11320                 }
11321                 // render the range of surfaces
11322                 if (ent == r_refdef.scene.worldentity)
11323                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11324                 else
11325                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11326         }
11327         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11328 }
11329
11330 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11331 {
11332         // transparent surfaces get pushed off into the transparent queue
11333         int surfacelistindex;
11334         const msurface_t *surface;
11335         vec3_t tempcenter, center;
11336         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11337         {
11338                 surface = texturesurfacelist[surfacelistindex];
11339                 if (r_transparent_sortsurfacesbynearest.integer)
11340                 {
11341                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11342                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11343                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11344                 }
11345                 else
11346                 {
11347                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11348                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11349                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11350                 }
11351                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11352                 if (rsurface.entity->transparent_offset) // transparent offset
11353                 {
11354                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11355                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11356                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11357                 }
11358                 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);
11359         }
11360 }
11361
11362 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11363 {
11364         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11365                 return;
11366         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11367                 return;
11368         RSurf_SetupDepthAndCulling();
11369         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11370         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11371         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11372         RSurf_DrawBatch();
11373 }
11374
11375 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11376 {
11377         CHECKGLERROR
11378         if (depthonly)
11379                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11380         else if (prepass)
11381         {
11382                 if (!rsurface.texture->currentnumlayers)
11383                         return;
11384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11385                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11386                 else
11387                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11388         }
11389         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11390                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11391         else if (!rsurface.texture->currentnumlayers)
11392                 return;
11393         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11394         {
11395                 // in the deferred case, transparent surfaces were queued during prepass
11396                 if (!r_shadow_usingdeferredprepass)
11397                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11398         }
11399         else
11400         {
11401                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11402                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11403         }
11404         CHECKGLERROR
11405 }
11406
11407 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11408 {
11409         int i, j;
11410         texture_t *texture;
11411         R_FrameData_SetMark();
11412         // break the surface list down into batches by texture and use of lightmapping
11413         for (i = 0;i < numsurfaces;i = j)
11414         {
11415                 j = i + 1;
11416                 // texture is the base texture pointer, rsurface.texture is the
11417                 // current frame/skin the texture is directing us to use (for example
11418                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11419                 // use skin 1 instead)
11420                 texture = surfacelist[i]->texture;
11421                 rsurface.texture = R_GetCurrentTexture(texture);
11422                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11423                 {
11424                         // if this texture is not the kind we want, skip ahead to the next one
11425                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11426                                 ;
11427                         continue;
11428                 }
11429                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11430                 {
11431                         rsurface.lightmaptexture = NULL;
11432                         rsurface.deluxemaptexture = NULL;
11433                         rsurface.uselightmaptexture = false;
11434                         // simply scan ahead until we find a different texture or lightmap state
11435                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11436                                 ;
11437                 }
11438                 else
11439                 {
11440                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11441                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11442                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11443                         // simply scan ahead until we find a different texture or lightmap state
11444                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11445                                 ;
11446                 }
11447                 // render the range of surfaces
11448                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11449         }
11450         R_FrameData_ReturnToMark();
11451 }
11452
11453 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11454 {
11455         CHECKGLERROR
11456         if (depthonly)
11457                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11458         else if (prepass)
11459         {
11460                 if (!rsurface.texture->currentnumlayers)
11461                         return;
11462                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11463                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11464                 else
11465                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11466         }
11467         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11468                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11469         else if (!rsurface.texture->currentnumlayers)
11470                 return;
11471         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11472         {
11473                 // in the deferred case, transparent surfaces were queued during prepass
11474                 if (!r_shadow_usingdeferredprepass)
11475                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11476         }
11477         else
11478         {
11479                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11480                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11481         }
11482         CHECKGLERROR
11483 }
11484
11485 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11486 {
11487         int i, j;
11488         texture_t *texture;
11489         R_FrameData_SetMark();
11490         // break the surface list down into batches by texture and use of lightmapping
11491         for (i = 0;i < numsurfaces;i = j)
11492         {
11493                 j = i + 1;
11494                 // texture is the base texture pointer, rsurface.texture is the
11495                 // current frame/skin the texture is directing us to use (for example
11496                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11497                 // use skin 1 instead)
11498                 texture = surfacelist[i]->texture;
11499                 rsurface.texture = R_GetCurrentTexture(texture);
11500                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11501                 {
11502                         // if this texture is not the kind we want, skip ahead to the next one
11503                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11504                                 ;
11505                         continue;
11506                 }
11507                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11508                 {
11509                         rsurface.lightmaptexture = NULL;
11510                         rsurface.deluxemaptexture = NULL;
11511                         rsurface.uselightmaptexture = false;
11512                         // simply scan ahead until we find a different texture or lightmap state
11513                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11514                                 ;
11515                 }
11516                 else
11517                 {
11518                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11519                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11520                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11521                         // simply scan ahead until we find a different texture or lightmap state
11522                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11523                                 ;
11524                 }
11525                 // render the range of surfaces
11526                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11527         }
11528         R_FrameData_ReturnToMark();
11529 }
11530
11531 float locboxvertex3f[6*4*3] =
11532 {
11533         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11534         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11535         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11536         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11537         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11538         1,0,0, 0,0,0, 0,1,0, 1,1,0
11539 };
11540
11541 unsigned short locboxelements[6*2*3] =
11542 {
11543          0, 1, 2, 0, 2, 3,
11544          4, 5, 6, 4, 6, 7,
11545          8, 9,10, 8,10,11,
11546         12,13,14, 12,14,15,
11547         16,17,18, 16,18,19,
11548         20,21,22, 20,22,23
11549 };
11550
11551 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11552 {
11553         int i, j;
11554         cl_locnode_t *loc = (cl_locnode_t *)ent;
11555         vec3_t mins, size;
11556         float vertex3f[6*4*3];
11557         CHECKGLERROR
11558         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11559         GL_DepthMask(false);
11560         GL_DepthRange(0, 1);
11561         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11562         GL_DepthTest(true);
11563         GL_CullFace(GL_NONE);
11564         R_EntityMatrix(&identitymatrix);
11565
11566 //      R_Mesh_ResetTextureState();
11567
11568         i = surfacelist[0];
11569         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11570                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11571                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11572                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11573
11574         if (VectorCompare(loc->mins, loc->maxs))
11575         {
11576                 VectorSet(size, 2, 2, 2);
11577                 VectorMA(loc->mins, -0.5f, size, mins);
11578         }
11579         else
11580         {
11581                 VectorCopy(loc->mins, mins);
11582                 VectorSubtract(loc->maxs, loc->mins, size);
11583         }
11584
11585         for (i = 0;i < 6*4*3;)
11586                 for (j = 0;j < 3;j++, i++)
11587                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11588
11589         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11590         R_SetupShader_Generic_NoTexture(false, false);
11591         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11592 }
11593
11594 void R_DrawLocs(void)
11595 {
11596         int index;
11597         cl_locnode_t *loc, *nearestloc;
11598         vec3_t center;
11599         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11600         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11601         {
11602                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11603                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11604         }
11605 }
11606
11607 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11608 {
11609         if (decalsystem->decals)
11610                 Mem_Free(decalsystem->decals);
11611         memset(decalsystem, 0, sizeof(*decalsystem));
11612 }
11613
11614 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)
11615 {
11616         tridecal_t *decal;
11617         tridecal_t *decals;
11618         int i;
11619
11620         // expand or initialize the system
11621         if (decalsystem->maxdecals <= decalsystem->numdecals)
11622         {
11623                 decalsystem_t old = *decalsystem;
11624                 qboolean useshortelements;
11625                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11626                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11627                 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)));
11628                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11629                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11630                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11631                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11632                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11633                 if (decalsystem->numdecals)
11634                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11635                 if (old.decals)
11636                         Mem_Free(old.decals);
11637                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11638                         decalsystem->element3i[i] = i;
11639                 if (useshortelements)
11640                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11641                                 decalsystem->element3s[i] = i;
11642         }
11643
11644         // grab a decal and search for another free slot for the next one
11645         decals = decalsystem->decals;
11646         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11647         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11648                 ;
11649         decalsystem->freedecal = i;
11650         if (decalsystem->numdecals <= i)
11651                 decalsystem->numdecals = i + 1;
11652
11653         // initialize the decal
11654         decal->lived = 0;
11655         decal->triangleindex = triangleindex;
11656         decal->surfaceindex = surfaceindex;
11657         decal->decalsequence = decalsequence;
11658         decal->color4f[0][0] = c0[0];
11659         decal->color4f[0][1] = c0[1];
11660         decal->color4f[0][2] = c0[2];
11661         decal->color4f[0][3] = 1;
11662         decal->color4f[1][0] = c1[0];
11663         decal->color4f[1][1] = c1[1];
11664         decal->color4f[1][2] = c1[2];
11665         decal->color4f[1][3] = 1;
11666         decal->color4f[2][0] = c2[0];
11667         decal->color4f[2][1] = c2[1];
11668         decal->color4f[2][2] = c2[2];
11669         decal->color4f[2][3] = 1;
11670         decal->vertex3f[0][0] = v0[0];
11671         decal->vertex3f[0][1] = v0[1];
11672         decal->vertex3f[0][2] = v0[2];
11673         decal->vertex3f[1][0] = v1[0];
11674         decal->vertex3f[1][1] = v1[1];
11675         decal->vertex3f[1][2] = v1[2];
11676         decal->vertex3f[2][0] = v2[0];
11677         decal->vertex3f[2][1] = v2[1];
11678         decal->vertex3f[2][2] = v2[2];
11679         decal->texcoord2f[0][0] = t0[0];
11680         decal->texcoord2f[0][1] = t0[1];
11681         decal->texcoord2f[1][0] = t1[0];
11682         decal->texcoord2f[1][1] = t1[1];
11683         decal->texcoord2f[2][0] = t2[0];
11684         decal->texcoord2f[2][1] = t2[1];
11685         TriangleNormal(v0, v1, v2, decal->plane);
11686         VectorNormalize(decal->plane);
11687         decal->plane[3] = DotProduct(v0, decal->plane);
11688 }
11689
11690 extern cvar_t cl_decals_bias;
11691 extern cvar_t cl_decals_models;
11692 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11693 // baseparms, parms, temps
11694 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)
11695 {
11696         int cornerindex;
11697         int index;
11698         float v[9][3];
11699         const float *vertex3f;
11700         const float *normal3f;
11701         int numpoints;
11702         float points[2][9][3];
11703         float temp[3];
11704         float tc[9][2];
11705         float f;
11706         float c[9][4];
11707         const int *e;
11708
11709         e = rsurface.modelelement3i + 3*triangleindex;
11710
11711         vertex3f = rsurface.modelvertex3f;
11712         normal3f = rsurface.modelnormal3f;
11713
11714         if (normal3f)
11715         {
11716                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11717                 {
11718                         index = 3*e[cornerindex];
11719                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11720                 }
11721         }
11722         else
11723         {
11724                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11725                 {
11726                         index = 3*e[cornerindex];
11727                         VectorCopy(vertex3f + index, v[cornerindex]);
11728                 }
11729         }
11730
11731         // cull backfaces
11732         //TriangleNormal(v[0], v[1], v[2], normal);
11733         //if (DotProduct(normal, localnormal) < 0.0f)
11734         //      continue;
11735         // clip by each of the box planes formed from the projection matrix
11736         // if anything survives, we emit the decal
11737         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]);
11738         if (numpoints < 3)
11739                 return;
11740         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]);
11741         if (numpoints < 3)
11742                 return;
11743         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]);
11744         if (numpoints < 3)
11745                 return;
11746         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]);
11747         if (numpoints < 3)
11748                 return;
11749         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]);
11750         if (numpoints < 3)
11751                 return;
11752         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]);
11753         if (numpoints < 3)
11754                 return;
11755         // some part of the triangle survived, so we have to accept it...
11756         if (dynamic)
11757         {
11758                 // dynamic always uses the original triangle
11759                 numpoints = 3;
11760                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11761                 {
11762                         index = 3*e[cornerindex];
11763                         VectorCopy(vertex3f + index, v[cornerindex]);
11764                 }
11765         }
11766         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11767         {
11768                 // convert vertex positions to texcoords
11769                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11770                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11771                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11772                 // calculate distance fade from the projection origin
11773                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11774                 f = bound(0.0f, f, 1.0f);
11775                 c[cornerindex][0] = r * f;
11776                 c[cornerindex][1] = g * f;
11777                 c[cornerindex][2] = b * f;
11778                 c[cornerindex][3] = 1.0f;
11779                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11780         }
11781         if (dynamic)
11782                 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);
11783         else
11784                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11785                         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);
11786 }
11787 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)
11788 {
11789         matrix4x4_t projection;
11790         decalsystem_t *decalsystem;
11791         qboolean dynamic;
11792         dp_model_t *model;
11793         const msurface_t *surface;
11794         const msurface_t *surfaces;
11795         const int *surfacelist;
11796         const texture_t *texture;
11797         int numtriangles;
11798         int numsurfacelist;
11799         int surfacelistindex;
11800         int surfaceindex;
11801         int triangleindex;
11802         float localorigin[3];
11803         float localnormal[3];
11804         float localmins[3];
11805         float localmaxs[3];
11806         float localsize;
11807         //float normal[3];
11808         float planes[6][4];
11809         float angles[3];
11810         bih_t *bih;
11811         int bih_triangles_count;
11812         int bih_triangles[256];
11813         int bih_surfaces[256];
11814
11815         decalsystem = &ent->decalsystem;
11816         model = ent->model;
11817         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11818         {
11819                 R_DecalSystem_Reset(&ent->decalsystem);
11820                 return;
11821         }
11822
11823         if (!model->brush.data_leafs && !cl_decals_models.integer)
11824         {
11825                 if (decalsystem->model)
11826                         R_DecalSystem_Reset(decalsystem);
11827                 return;
11828         }
11829
11830         if (decalsystem->model != model)
11831                 R_DecalSystem_Reset(decalsystem);
11832         decalsystem->model = model;
11833
11834         RSurf_ActiveModelEntity(ent, true, false, false);
11835
11836         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11837         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11838         VectorNormalize(localnormal);
11839         localsize = worldsize*rsurface.inversematrixscale;
11840         localmins[0] = localorigin[0] - localsize;
11841         localmins[1] = localorigin[1] - localsize;
11842         localmins[2] = localorigin[2] - localsize;
11843         localmaxs[0] = localorigin[0] + localsize;
11844         localmaxs[1] = localorigin[1] + localsize;
11845         localmaxs[2] = localorigin[2] + localsize;
11846
11847         //VectorCopy(localnormal, planes[4]);
11848         //VectorVectors(planes[4], planes[2], planes[0]);
11849         AnglesFromVectors(angles, localnormal, NULL, false);
11850         AngleVectors(angles, planes[0], planes[2], planes[4]);
11851         VectorNegate(planes[0], planes[1]);
11852         VectorNegate(planes[2], planes[3]);
11853         VectorNegate(planes[4], planes[5]);
11854         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11855         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11856         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11857         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11858         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11859         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11860
11861 #if 1
11862 // works
11863 {
11864         matrix4x4_t forwardprojection;
11865         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11866         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11867 }
11868 #else
11869 // broken
11870 {
11871         float projectionvector[4][3];
11872         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11873         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11874         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11875         projectionvector[0][0] = planes[0][0] * ilocalsize;
11876         projectionvector[0][1] = planes[1][0] * ilocalsize;
11877         projectionvector[0][2] = planes[2][0] * ilocalsize;
11878         projectionvector[1][0] = planes[0][1] * ilocalsize;
11879         projectionvector[1][1] = planes[1][1] * ilocalsize;
11880         projectionvector[1][2] = planes[2][1] * ilocalsize;
11881         projectionvector[2][0] = planes[0][2] * ilocalsize;
11882         projectionvector[2][1] = planes[1][2] * ilocalsize;
11883         projectionvector[2][2] = planes[2][2] * ilocalsize;
11884         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11885         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11886         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11887         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11888 }
11889 #endif
11890
11891         dynamic = model->surfmesh.isanimated;
11892         numsurfacelist = model->nummodelsurfaces;
11893         surfacelist = model->sortedmodelsurfaces;
11894         surfaces = model->data_surfaces;
11895
11896         bih = NULL;
11897         bih_triangles_count = -1;
11898         if(!dynamic)
11899         {
11900                 if(model->render_bih.numleafs)
11901                         bih = &model->render_bih;
11902                 else if(model->collision_bih.numleafs)
11903                         bih = &model->collision_bih;
11904         }
11905         if(bih)
11906                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11907         if(bih_triangles_count == 0)
11908                 return;
11909         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11910                 return;
11911         if(bih_triangles_count > 0)
11912         {
11913                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11914                 {
11915                         surfaceindex = bih_surfaces[triangleindex];
11916                         surface = surfaces + surfaceindex;
11917                         texture = surface->texture;
11918                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11919                                 continue;
11920                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11921                                 continue;
11922                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11923                 }
11924         }
11925         else
11926         {
11927                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11928                 {
11929                         surfaceindex = surfacelist[surfacelistindex];
11930                         surface = surfaces + surfaceindex;
11931                         // check cull box first because it rejects more than any other check
11932                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11933                                 continue;
11934                         // skip transparent surfaces
11935                         texture = surface->texture;
11936                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11937                                 continue;
11938                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11939                                 continue;
11940                         numtriangles = surface->num_triangles;
11941                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11942                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11943                 }
11944         }
11945 }
11946
11947 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11948 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)
11949 {
11950         int renderentityindex;
11951         float worldmins[3];
11952         float worldmaxs[3];
11953         entity_render_t *ent;
11954
11955         if (!cl_decals_newsystem.integer)
11956                 return;
11957
11958         worldmins[0] = worldorigin[0] - worldsize;
11959         worldmins[1] = worldorigin[1] - worldsize;
11960         worldmins[2] = worldorigin[2] - worldsize;
11961         worldmaxs[0] = worldorigin[0] + worldsize;
11962         worldmaxs[1] = worldorigin[1] + worldsize;
11963         worldmaxs[2] = worldorigin[2] + worldsize;
11964
11965         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11966
11967         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11968         {
11969                 ent = r_refdef.scene.entities[renderentityindex];
11970                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11971                         continue;
11972
11973                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11974         }
11975 }
11976
11977 typedef struct r_decalsystem_splatqueue_s
11978 {
11979         vec3_t worldorigin;
11980         vec3_t worldnormal;
11981         float color[4];
11982         float tcrange[4];
11983         float worldsize;
11984         int decalsequence;
11985 }
11986 r_decalsystem_splatqueue_t;
11987
11988 int r_decalsystem_numqueued = 0;
11989 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11990
11991 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)
11992 {
11993         r_decalsystem_splatqueue_t *queue;
11994
11995         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11996                 return;
11997
11998         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11999         VectorCopy(worldorigin, queue->worldorigin);
12000         VectorCopy(worldnormal, queue->worldnormal);
12001         Vector4Set(queue->color, r, g, b, a);
12002         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12003         queue->worldsize = worldsize;
12004         queue->decalsequence = cl.decalsequence++;
12005 }
12006
12007 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12008 {
12009         int i;
12010         r_decalsystem_splatqueue_t *queue;
12011
12012         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12013                 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);
12014         r_decalsystem_numqueued = 0;
12015 }
12016
12017 extern cvar_t cl_decals_max;
12018 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12019 {
12020         int i;
12021         decalsystem_t *decalsystem = &ent->decalsystem;
12022         int numdecals;
12023         int killsequence;
12024         tridecal_t *decal;
12025         float frametime;
12026         float lifetime;
12027
12028         if (!decalsystem->numdecals)
12029                 return;
12030
12031         if (r_showsurfaces.integer)
12032                 return;
12033
12034         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12035         {
12036                 R_DecalSystem_Reset(decalsystem);
12037                 return;
12038         }
12039
12040         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12041         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12042
12043         if (decalsystem->lastupdatetime)
12044                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12045         else
12046                 frametime = 0;
12047         decalsystem->lastupdatetime = r_refdef.scene.time;
12048         numdecals = decalsystem->numdecals;
12049
12050         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12051         {
12052                 if (decal->color4f[0][3])
12053                 {
12054                         decal->lived += frametime;
12055                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12056                         {
12057                                 memset(decal, 0, sizeof(*decal));
12058                                 if (decalsystem->freedecal > i)
12059                                         decalsystem->freedecal = i;
12060                         }
12061                 }
12062         }
12063         decal = decalsystem->decals;
12064         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12065                 numdecals--;
12066
12067         // collapse the array by shuffling the tail decals into the gaps
12068         for (;;)
12069         {
12070                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12071                         decalsystem->freedecal++;
12072                 if (decalsystem->freedecal == numdecals)
12073                         break;
12074                 decal[decalsystem->freedecal] = decal[--numdecals];
12075         }
12076
12077         decalsystem->numdecals = numdecals;
12078
12079         if (numdecals <= 0)
12080         {
12081                 // if there are no decals left, reset decalsystem
12082                 R_DecalSystem_Reset(decalsystem);
12083         }
12084 }
12085
12086 extern skinframe_t *decalskinframe;
12087 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12088 {
12089         int i;
12090         decalsystem_t *decalsystem = &ent->decalsystem;
12091         int numdecals;
12092         tridecal_t *decal;
12093         float faderate;
12094         float alpha;
12095         float *v3f;
12096         float *c4f;
12097         float *t2f;
12098         const int *e;
12099         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12100         int numtris = 0;
12101
12102         numdecals = decalsystem->numdecals;
12103         if (!numdecals)
12104                 return;
12105
12106         if (r_showsurfaces.integer)
12107                 return;
12108
12109         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12110         {
12111                 R_DecalSystem_Reset(decalsystem);
12112                 return;
12113         }
12114
12115         // if the model is static it doesn't matter what value we give for
12116         // wantnormals and wanttangents, so this logic uses only rules applicable
12117         // to a model, knowing that they are meaningless otherwise
12118         if (ent == r_refdef.scene.worldentity)
12119                 RSurf_ActiveWorldEntity();
12120         else
12121                 RSurf_ActiveModelEntity(ent, false, false, false);
12122
12123         decalsystem->lastupdatetime = r_refdef.scene.time;
12124
12125         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12126
12127         // update vertex positions for animated models
12128         v3f = decalsystem->vertex3f;
12129         c4f = decalsystem->color4f;
12130         t2f = decalsystem->texcoord2f;
12131         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12132         {
12133                 if (!decal->color4f[0][3])
12134                         continue;
12135
12136                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12137                         continue;
12138
12139                 // skip backfaces
12140                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12141                         continue;
12142
12143                 // update color values for fading decals
12144                 if (decal->lived >= cl_decals_time.value)
12145                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12146                 else
12147                         alpha = 1.0f;
12148
12149                 c4f[ 0] = decal->color4f[0][0] * alpha;
12150                 c4f[ 1] = decal->color4f[0][1] * alpha;
12151                 c4f[ 2] = decal->color4f[0][2] * alpha;
12152                 c4f[ 3] = 1;
12153                 c4f[ 4] = decal->color4f[1][0] * alpha;
12154                 c4f[ 5] = decal->color4f[1][1] * alpha;
12155                 c4f[ 6] = decal->color4f[1][2] * alpha;
12156                 c4f[ 7] = 1;
12157                 c4f[ 8] = decal->color4f[2][0] * alpha;
12158                 c4f[ 9] = decal->color4f[2][1] * alpha;
12159                 c4f[10] = decal->color4f[2][2] * alpha;
12160                 c4f[11] = 1;
12161
12162                 t2f[0] = decal->texcoord2f[0][0];
12163                 t2f[1] = decal->texcoord2f[0][1];
12164                 t2f[2] = decal->texcoord2f[1][0];
12165                 t2f[3] = decal->texcoord2f[1][1];
12166                 t2f[4] = decal->texcoord2f[2][0];
12167                 t2f[5] = decal->texcoord2f[2][1];
12168
12169                 // update vertex positions for animated models
12170                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12171                 {
12172                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12173                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12174                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12175                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12176                 }
12177                 else
12178                 {
12179                         VectorCopy(decal->vertex3f[0], v3f);
12180                         VectorCopy(decal->vertex3f[1], v3f + 3);
12181                         VectorCopy(decal->vertex3f[2], v3f + 6);
12182                 }
12183
12184                 if (r_refdef.fogenabled)
12185                 {
12186                         alpha = RSurf_FogVertex(v3f);
12187                         VectorScale(c4f, alpha, c4f);
12188                         alpha = RSurf_FogVertex(v3f + 3);
12189                         VectorScale(c4f + 4, alpha, c4f + 4);
12190                         alpha = RSurf_FogVertex(v3f + 6);
12191                         VectorScale(c4f + 8, alpha, c4f + 8);
12192                 }
12193
12194                 v3f += 9;
12195                 c4f += 12;
12196                 t2f += 6;
12197                 numtris++;
12198         }
12199
12200         if (numtris > 0)
12201         {
12202                 r_refdef.stats[r_stat_drawndecals] += numtris;
12203
12204                 // now render the decals all at once
12205                 // (this assumes they all use one particle font texture!)
12206                 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);
12207 //              R_Mesh_ResetTextureState();
12208                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12209                 GL_DepthMask(false);
12210                 GL_DepthRange(0, 1);
12211                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12212                 GL_DepthTest(true);
12213                 GL_CullFace(GL_NONE);
12214                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12215                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12216                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12217         }
12218 }
12219
12220 static void R_DrawModelDecals(void)
12221 {
12222         int i, numdecals;
12223
12224         // fade faster when there are too many decals
12225         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12226         for (i = 0;i < r_refdef.scene.numentities;i++)
12227                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12228
12229         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12230         for (i = 0;i < r_refdef.scene.numentities;i++)
12231                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12232                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12233
12234         R_DecalSystem_ApplySplatEntitiesQueue();
12235
12236         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12237         for (i = 0;i < r_refdef.scene.numentities;i++)
12238                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12239
12240         r_refdef.stats[r_stat_totaldecals] += numdecals;
12241
12242         if (r_showsurfaces.integer)
12243                 return;
12244
12245         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12246
12247         for (i = 0;i < r_refdef.scene.numentities;i++)
12248         {
12249                 if (!r_refdef.viewcache.entityvisible[i])
12250                         continue;
12251                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12252                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12253         }
12254 }
12255
12256 extern cvar_t mod_collision_bih;
12257 static void R_DrawDebugModel(void)
12258 {
12259         entity_render_t *ent = rsurface.entity;
12260         int i, j, k, l, flagsmask;
12261         const msurface_t *surface;
12262         dp_model_t *model = ent->model;
12263         vec3_t v;
12264
12265         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12266                 return;
12267
12268         if (r_showoverdraw.value > 0)
12269         {
12270                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12271                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12272                 R_SetupShader_Generic_NoTexture(false, false);
12273                 GL_DepthTest(false);
12274                 GL_DepthMask(false);
12275                 GL_DepthRange(0, 1);
12276                 GL_BlendFunc(GL_ONE, GL_ONE);
12277                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12278                 {
12279                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12280                                 continue;
12281                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12282                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12283                         {
12284                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12285                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12286                                 if (!rsurface.texture->currentlayers->depthmask)
12287                                         GL_Color(c, 0, 0, 1.0f);
12288                                 else if (ent == r_refdef.scene.worldentity)
12289                                         GL_Color(c, c, c, 1.0f);
12290                                 else
12291                                         GL_Color(0, c, 0, 1.0f);
12292                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12293                                 RSurf_DrawBatch();
12294                         }
12295                 }
12296                 rsurface.texture = NULL;
12297         }
12298
12299         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12300
12301 //      R_Mesh_ResetTextureState();
12302         R_SetupShader_Generic_NoTexture(false, false);
12303         GL_DepthRange(0, 1);
12304         GL_DepthTest(!r_showdisabledepthtest.integer);
12305         GL_DepthMask(false);
12306         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12307
12308         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12309         {
12310                 int triangleindex;
12311                 int bihleafindex;
12312                 qboolean cullbox = false;
12313                 const q3mbrush_t *brush;
12314                 const bih_t *bih = &model->collision_bih;
12315                 const bih_leaf_t *bihleaf;
12316                 float vertex3f[3][3];
12317                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12318                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12319                 {
12320                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12321                                 continue;
12322                         switch (bihleaf->type)
12323                         {
12324                         case BIH_BRUSH:
12325                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12326                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12327                                 {
12328                                         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);
12329                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12330                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12331                                 }
12332                                 break;
12333                         case BIH_COLLISIONTRIANGLE:
12334                                 triangleindex = bihleaf->itemindex;
12335                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12336                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12337                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12338                                 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);
12339                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12340                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12341                                 break;
12342                         case BIH_RENDERTRIANGLE:
12343                                 triangleindex = bihleaf->itemindex;
12344                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12345                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12346                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12347                                 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);
12348                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12349                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12350                                 break;
12351                         }
12352                 }
12353         }
12354
12355         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12356
12357 #ifndef USE_GLES2
12358         if (r_showtris.integer && qglPolygonMode)
12359         {
12360                 if (r_showdisabledepthtest.integer)
12361                 {
12362                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12363                         GL_DepthMask(false);
12364                 }
12365                 else
12366                 {
12367                         GL_BlendFunc(GL_ONE, GL_ZERO);
12368                         GL_DepthMask(true);
12369                 }
12370                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12371                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12372                 {
12373                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12374                                 continue;
12375                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12376                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12377                         {
12378                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12379                                 if (!rsurface.texture->currentlayers->depthmask)
12380                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12381                                 else if (ent == r_refdef.scene.worldentity)
12382                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12383                                 else
12384                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12385                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12386                                 RSurf_DrawBatch();
12387                         }
12388                 }
12389                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12390                 rsurface.texture = NULL;
12391         }
12392
12393         if (r_shownormals.value != 0 && qglBegin)
12394         {
12395                 if (r_showdisabledepthtest.integer)
12396                 {
12397                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12398                         GL_DepthMask(false);
12399                 }
12400                 else
12401                 {
12402                         GL_BlendFunc(GL_ONE, GL_ZERO);
12403                         GL_DepthMask(true);
12404                 }
12405                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12406                 {
12407                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12408                                 continue;
12409                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12410                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12411                         {
12412                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12413                                 qglBegin(GL_LINES);
12414                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12415                                 {
12416                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12417                                         {
12418                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12419                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12420                                                 qglVertex3f(v[0], v[1], v[2]);
12421                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12422                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12423                                                 qglVertex3f(v[0], v[1], v[2]);
12424                                         }
12425                                 }
12426                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12427                                 {
12428                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12429                                         {
12430                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12431                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12432                                                 qglVertex3f(v[0], v[1], v[2]);
12433                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12434                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12435                                                 qglVertex3f(v[0], v[1], v[2]);
12436                                         }
12437                                 }
12438                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12439                                 {
12440                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12441                                         {
12442                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12443                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12444                                                 qglVertex3f(v[0], v[1], v[2]);
12445                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12446                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12447                                                 qglVertex3f(v[0], v[1], v[2]);
12448                                         }
12449                                 }
12450                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12451                                 {
12452                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12453                                         {
12454                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12455                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12456                                                 qglVertex3f(v[0], v[1], v[2]);
12457                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12458                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12459                                                 qglVertex3f(v[0], v[1], v[2]);
12460                                         }
12461                                 }
12462                                 qglEnd();
12463                                 CHECKGLERROR
12464                         }
12465                 }
12466                 rsurface.texture = NULL;
12467         }
12468 #endif
12469 }
12470
12471 int r_maxsurfacelist = 0;
12472 const msurface_t **r_surfacelist = NULL;
12473 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12474 {
12475         int i, j, endj, flagsmask;
12476         dp_model_t *model = r_refdef.scene.worldmodel;
12477         msurface_t *surfaces;
12478         unsigned char *update;
12479         int numsurfacelist = 0;
12480         if (model == NULL)
12481                 return;
12482
12483         if (r_maxsurfacelist < model->num_surfaces)
12484         {
12485                 r_maxsurfacelist = model->num_surfaces;
12486                 if (r_surfacelist)
12487                         Mem_Free((msurface_t**)r_surfacelist);
12488                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12489         }
12490
12491         RSurf_ActiveWorldEntity();
12492
12493         surfaces = model->data_surfaces;
12494         update = model->brushq1.lightmapupdateflags;
12495
12496         // update light styles on this submodel
12497         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12498         {
12499                 model_brush_lightstyleinfo_t *style;
12500                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12501                 {
12502                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12503                         {
12504                                 int *list = style->surfacelist;
12505                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12506                                 for (j = 0;j < style->numsurfaces;j++)
12507                                         update[list[j]] = true;
12508                         }
12509                 }
12510         }
12511
12512         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12513
12514         if (debug)
12515         {
12516                 R_DrawDebugModel();
12517                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12518                 return;
12519         }
12520
12521         rsurface.lightmaptexture = NULL;
12522         rsurface.deluxemaptexture = NULL;
12523         rsurface.uselightmaptexture = false;
12524         rsurface.texture = NULL;
12525         rsurface.rtlight = NULL;
12526         numsurfacelist = 0;
12527         // add visible surfaces to draw list
12528         for (i = 0;i < model->nummodelsurfaces;i++)
12529         {
12530                 j = model->sortedmodelsurfaces[i];
12531                 if (r_refdef.viewcache.world_surfacevisible[j])
12532                         r_surfacelist[numsurfacelist++] = surfaces + j;
12533         }
12534         // update lightmaps if needed
12535         if (model->brushq1.firstrender)
12536         {
12537                 model->brushq1.firstrender = false;
12538                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12539                         if (update[j])
12540                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12541         }
12542         else if (update)
12543         {
12544                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12545                         if (r_refdef.viewcache.world_surfacevisible[j])
12546                                 if (update[j])
12547                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12548         }
12549         // don't do anything if there were no surfaces
12550         if (!numsurfacelist)
12551         {
12552                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12553                 return;
12554         }
12555         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12556
12557         // add to stats if desired
12558         if (r_speeds.integer && !skysurfaces && !depthonly)
12559         {
12560                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12561                 for (j = 0;j < numsurfacelist;j++)
12562                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12563         }
12564
12565         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12566 }
12567
12568 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12569 {
12570         int i, j, endj, flagsmask;
12571         dp_model_t *model = ent->model;
12572         msurface_t *surfaces;
12573         unsigned char *update;
12574         int numsurfacelist = 0;
12575         if (model == NULL)
12576                 return;
12577
12578         if (r_maxsurfacelist < model->num_surfaces)
12579         {
12580                 r_maxsurfacelist = model->num_surfaces;
12581                 if (r_surfacelist)
12582                         Mem_Free((msurface_t **)r_surfacelist);
12583                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12584         }
12585
12586         // if the model is static it doesn't matter what value we give for
12587         // wantnormals and wanttangents, so this logic uses only rules applicable
12588         // to a model, knowing that they are meaningless otherwise
12589         if (ent == r_refdef.scene.worldentity)
12590                 RSurf_ActiveWorldEntity();
12591         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12592                 RSurf_ActiveModelEntity(ent, false, false, false);
12593         else if (prepass)
12594                 RSurf_ActiveModelEntity(ent, true, true, true);
12595         else if (depthonly)
12596         {
12597                 switch (vid.renderpath)
12598                 {
12599                 case RENDERPATH_GL20:
12600                 case RENDERPATH_D3D9:
12601                 case RENDERPATH_D3D10:
12602                 case RENDERPATH_D3D11:
12603                 case RENDERPATH_SOFT:
12604                 case RENDERPATH_GLES2:
12605                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12606                         break;
12607                 case RENDERPATH_GL11:
12608                 case RENDERPATH_GL13:
12609                 case RENDERPATH_GLES1:
12610                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12611                         break;
12612                 }
12613         }
12614         else
12615         {
12616                 switch (vid.renderpath)
12617                 {
12618                 case RENDERPATH_GL20:
12619                 case RENDERPATH_D3D9:
12620                 case RENDERPATH_D3D10:
12621                 case RENDERPATH_D3D11:
12622                 case RENDERPATH_SOFT:
12623                 case RENDERPATH_GLES2:
12624                         RSurf_ActiveModelEntity(ent, true, true, false);
12625                         break;
12626                 case RENDERPATH_GL11:
12627                 case RENDERPATH_GL13:
12628                 case RENDERPATH_GLES1:
12629                         RSurf_ActiveModelEntity(ent, true, false, false);
12630                         break;
12631                 }
12632         }
12633
12634         surfaces = model->data_surfaces;
12635         update = model->brushq1.lightmapupdateflags;
12636
12637         // update light styles
12638         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12639         {
12640                 model_brush_lightstyleinfo_t *style;
12641                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12642                 {
12643                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12644                         {
12645                                 int *list = style->surfacelist;
12646                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12647                                 for (j = 0;j < style->numsurfaces;j++)
12648                                         update[list[j]] = true;
12649                         }
12650                 }
12651         }
12652
12653         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12654
12655         if (debug)
12656         {
12657                 R_DrawDebugModel();
12658                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12659                 return;
12660         }
12661
12662         rsurface.lightmaptexture = NULL;
12663         rsurface.deluxemaptexture = NULL;
12664         rsurface.uselightmaptexture = false;
12665         rsurface.texture = NULL;
12666         rsurface.rtlight = NULL;
12667         numsurfacelist = 0;
12668         // add visible surfaces to draw list
12669         for (i = 0;i < model->nummodelsurfaces;i++)
12670                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12671         // don't do anything if there were no surfaces
12672         if (!numsurfacelist)
12673         {
12674                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12675                 return;
12676         }
12677         // update lightmaps if needed
12678         if (update)
12679         {
12680                 int updated = 0;
12681                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12682                 {
12683                         if (update[j])
12684                         {
12685                                 updated++;
12686                                 R_BuildLightMap(ent, surfaces + j);
12687                         }
12688                 }
12689         }
12690
12691         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12692
12693         // add to stats if desired
12694         if (r_speeds.integer && !skysurfaces && !depthonly)
12695         {
12696                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12697                 for (j = 0;j < numsurfacelist;j++)
12698                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12699         }
12700
12701         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12702 }
12703
12704 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12705 {
12706         static texture_t texture;
12707         static msurface_t surface;
12708         const msurface_t *surfacelist = &surface;
12709
12710         // fake enough texture and surface state to render this geometry
12711
12712         texture.update_lastrenderframe = -1; // regenerate this texture
12713         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12714         texture.currentskinframe = skinframe;
12715         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12716         texture.offsetmapping = OFFSETMAPPING_OFF;
12717         texture.offsetscale = 1;
12718         texture.specularscalemod = 1;
12719         texture.specularpowermod = 1;
12720         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12721         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12722         // JUST GREP FOR "specularscalemod = 1".
12723
12724         surface.texture = &texture;
12725         surface.num_triangles = numtriangles;
12726         surface.num_firsttriangle = firsttriangle;
12727         surface.num_vertices = numvertices;
12728         surface.num_firstvertex = firstvertex;
12729
12730         // now render it
12731         rsurface.texture = R_GetCurrentTexture(surface.texture);
12732         rsurface.lightmaptexture = NULL;
12733         rsurface.deluxemaptexture = NULL;
12734         rsurface.uselightmaptexture = false;
12735         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12736 }
12737
12738 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)
12739 {
12740         static msurface_t surface;
12741         const msurface_t *surfacelist = &surface;
12742
12743         // fake enough texture and surface state to render this geometry
12744         surface.texture = texture;
12745         surface.num_triangles = numtriangles;
12746         surface.num_firsttriangle = firsttriangle;
12747         surface.num_vertices = numvertices;
12748         surface.num_firstvertex = firstvertex;
12749
12750         // now render it
12751         rsurface.texture = R_GetCurrentTexture(surface.texture);
12752         rsurface.lightmaptexture = NULL;
12753         rsurface.deluxemaptexture = NULL;
12754         rsurface.uselightmaptexture = false;
12755         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12756 }